Các loại chuỗi Haskell thường được đề nghị có vẻ là ByteString hoặc Text. Tôi thường làm việc với một số lượng rất lớn các chuỗi ngắn (từ tiếng Anh), và thường cần lưu trữ chúng trong một bảng tra cứu như Data.Map. Trong nhiều trường hợp, tôi thấy rằng trong trường hợp này, một bảng các chuỗi có thể chiếm ít bộ nhớ hơn sau đó là một bảng ByteStrings. Data.Vector không được phân loại của Word8 cũng nhỏ hơn nhiều so với ByteStrings.Các chuỗi ký hiệu hiệu quả trong Haskell
Phương pháp hay nhất khi cần lưu trữ và so sánh số lượng lớn các chuỗi nhỏ trong Haskell là gì?
Dưới đây tôi đã cố gắng cô đọng một trường hợp có vấn đề cụ thể vào một ví dụ nhỏ:
import qualified Data.ByteString.Lazy.Char8 as S
import qualified Data.ByteString as Strict
import qualified Data.Map as Map
import qualified Data.Vector.Unboxed as U
import qualified Data.Serialize as Serialize
import Control.Monad.State
main = putStr
. unlines . map show . flip evalState (0,Map.empty)
. mapM toInt
. S.words
=<<
S.getContents
toInt x = do
let x' =
U.fromList . Strict.unpack . -- Comment this line to increase memory usage
Serialize.encode $ x
(i,t) <- get
case Map.lookup x' t of
Just j -> return j
Nothing -> do
let i' = i + (1::Int)
put (i', Map.insert x' i t)
return i
Khi tôi chạy trên một tập tin có chứa khoảng 400.000 lời của văn bản tiếng Anh, phiên bản với các phím bytestring nghiêm ngặt sử dụng khoảng 50MB bộ nhớ, một với các vectơ Word8 sử dụng 6MB.
Bạn đang sử dụng những chuỗi đó để làm gì? Nó là một loại từ điển nào đó? – ARRG
Bạn có thể đưa ra một số ví dụ mã trong đó ByteStrings chiếm nhiều bộ nhớ hơn Strings hoặc bộ nhớ "nhiều hơn" so với các vectơ Word8 không? Tôi không thể hiểu tại sao điều đó xảy ra trừ khi bạn đang làm điều gì đó kỳ lạ. – shang
@shang: Tôi có thể tưởng tượng điều này xảy ra nếu bạn đang phạm sai lầm so sánh kích thước của một bản đồ đầy đủ các ByteStrings nghiêm ngặt với một bản đồ có chứa chuỗi khối. Mặc dù nhiều chi tiết hơn sẽ hữu ích. Một chương trình thử nghiệm ngắn cho thấy vấn đề sẽ đặc biệt tốt đẹp. – hammar