解码Text对象的大量内存开销

时间:2016-02-20 12:11:19

标签: haskell

我正在对Binary个对象进行Text序列化和反序列化,我注意到未解码的thunk使用的内存比实际长度更多数据。我创建了一个可以重现问题的玩具程序(有关完整设置,请参阅this gist):

import qualified Data.ByteString.Lazy as B
import qualified Data.Text as T

main = do
    handle <- openBinaryFile "testfile" ReadMode
    initSize <- hFileSize handle
    str <- B.hGet handle (fromInteger initSize)
    hClose handle
    --msgs :: [T.Text]
    let (_, msgs) = decodeMany str
    --here we fool the GC into retaining the thunks in msgs
    chr <- readLn
    print $ map (max chr) $ map (T.foldl1 max) msgs
    --now we let it collect them
    num1 <- readLn
    print (num1 + 1)

当我运行它时:

$ ./Test2 +RTS -S
    Alloc    Copied     Live    GC    GC     TOT     TOT  Page Flts
    bytes     bytes     bytes  user  elap    user    elap
   108112      6936     82320  0.00  0.01    0.01    0.33    0    0  (Gen:  1)
     1720      6152     73400  0.00  0.00    0.02    0.66    0    0  (Gen:  1)
't'
   874672     28544    408856  0.00  0.00    0.02    4.14    0    0  (Gen:  0) **
   519864     33200    434680  0.00  0.00    0.02    4.14    0    0  (Gen:  0) **
"vxvxvvvxvxvvvxvxvvvxvxvvvxvxvvvxvxvvx"
    95504      8424     83680  0.00  0.00    0.02    4.45    0    0  (Gen:  1)
8
9
    30992      6984     65824  0.00  0.00    0.02    6.48    0    0  (Gen:  1)

因此需要超过300k(请参阅**标记的行)来存储18k的文本。 (我已经检查了堆配置文件,它们主要是ARR_WORDS。)

另一方面,如果我用T.foldl1替换T.foldl1',垃圾收集器就能收回thunk,并且标记的行变为

   781336      8432     83680  0.00  0.00    0.02    6.48    0    0  (Gen:  1)

所以它分配的数量相同,但是一旦强制Text个对象就回收它。我想象我做i / o的方式和我使用的类型的一些组合使它为每个解码的字符串制作一个完整的文件副本(因为37个字符串* 18k = 666k)。

如何让解码过程不分配和保留这么多内存?

0 个答案:

没有答案