Tôi đã xem xét các tùy chọn hiện tại cho regex trong Haskell và tôi muốn hiểu khoảng cách về hiệu suất đến từ đâu khi so sánh các tùy chọn khác nhau và đặc biệt với một lệnh gọi đơn giản là grep .. .Hiệu suất của Haskell Regex
tôi có một tương đối nhỏ (~ 110 triệu, so với bình thường nhiều 10s của G trong hầu hết các trường hợp sử dụng của tôi) trace file:
$ du radixtracefile
113120 radixtracefile
$ wc -l radixtracefile
1051565 radixtracefile
- lần đầu tiên tôi đã cố gắng để tìm cách nhiều trận đấu của (tùy ý) mẫu
.*504.*ll
là trong đó thông qua grep:
$ time grep -nE ".*504.*ll" radixtracefile | wc -l
309
real 0m0.211s
user 0m0.202s
sys 0m0.010s
- Tôi nhìn Text.Regex.TDFA (phiên bản 1.2.1) với Data.ByteString:
import Control.Monad.Loops
import Data.Maybe
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import Text.Regex.TDFA
import qualified Data.ByteString as B
main = do
f <- B.readFile "radixtracefile"
matches :: [[B.ByteString]] <- f =~~ ".*504.*ll"
mapM_ (putStrLn . show . head) matches
Xây dựng và chạy:
$ ghc -O2 test-TDFA.hs -XScopedTypeVariables
[1 of 1] Compiling Main (test-TDFA.hs, test-TDFA.o)
Linking test-TDFA ...
$ time ./test-TDFA | wc -l
309
real 0m4.463s
user 0m4.431s
sys 0m0.036s
- Sau đó, tôi nhìn vào Data.Text.ICU.Regex (phiên bản 0.7.0.1) với sự hỗ trợ Unicode:
import Control.Monad.Loops
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import Data.Text.ICU.Regex
main = do
re <- regex [] $ T.pack ".*504.*ll"
f <- TIO.readFile "radixtracefile"
setText re f
whileM_ (findNext re) $ do
a <- start re 0
putStrLn $ "last match at :"++(show a)
Xây dựng và chạy:
$ ghc -O2 test-ICU.hs
[1 of 1] Compiling Main (test-ICU.hs, test-ICU.o)
Linking test-ICU ...
$ time ./test-ICU | wc -l
309
real 1m36.407s
user 1m36.090s
sys 0m0.169s
Tôi sử dụng phiên bản 7.6.3. Tôi đã không có dịp thử nghiệm các tùy chọn regex Haskell khác. Tôi biết rằng tôi sẽ không nhận được hiệu suất mà tôi đã có với grep và đã được hạnh phúc hơn với điều đó, nhưng nhiều hơn hoặc ít hơn 20 lần chậm hơn cho TDFA và ByteString ... Điều đó là rất đáng sợ. Và tôi không thể thực sự hiểu tại sao nó là những gì nó được, như tôi ngây thơ mặc dù rằng đây là một wrapper trên một phụ trợ bản địa ... Tôi bằng cách nào đó không sử dụng các mô-đun một cách chính xác?
(Và chúng ta không đề cập đến ICU + chữ kết hợp mà đang trải qua mái nhà)
Có một lựa chọn mà tôi đã không kiểm tra được nêu ra mà có thể làm tôi hạnh phúc hơn?
EDIT:
- Text.Regex.PCRE (phiên bản 0.94.4) với Data.ByteString:
import Control.Monad.Loops
import Data.Maybe
import Text.Regex.PCRE
import qualified Data.ByteString as B
main = do
f <- B.readFile "radixtracefile"
matches :: [[B.ByteString]] <- f =~~ ".*504.*ll"
mapM_ (putStrLn . show . head) matches
Xây dựng và chạy:
$ ghc -O2 test-PCRE.hs -XScopedTypeVariables
[1 of 1] Compiling Main (test-PCRE.hs, test-PCRE.o)
Linking test-PCRE ...
$ time ./test-PCRE | wc -l
309
real 0m1.442s
user 0m1.412s
sys 0m0.031s
Tốt hơn, nhưng vẫn với một yếu tố ~ 7-ish ...
Bạn đang nói về cách thực hiện chính xác của Haskell? Điều đó có thể tạo nên sự khác biệt. – vonbrand
@vonbrand: Đoạn trích đề cập đến 'ghc -O2'. Liệu vấn đề phiên bản (trình biên dịch/thư viện), hay bạn muốn biết điều gì? – Bergi
@vonbrand: '$ ghc --version' cung cấp cho' Hệ thống biên dịch Glorious Glasgow Haskell, phiên bản 7.6.3'. 'danh sách cabex regex-tdfa' cho (trong số những thứ khác)' regex-tdfa [...] Phiên bản cài đặt: 1.2.1', và 'cabal list text-icu',' text-icu [...] Phiên bản cài đặt : 0,7.0.1'. Đó có phải là thông tin bạn đang tìm kiếm không? Tôi sẽ chỉnh sửa câu hỏi của mình để thêm thông tin này. – gameboo