【发布时间】:2014-01-18 21:16:03
【问题描述】:
我一直在尝试使用 haskell 程序阅读和索引一组链接和维基百科摘要。目的是
- 从文件中读取一行
- 解析它
- 对行的某些部分以及文件中的偏移量进行哈希和索引,以便我以后找到它
问题是我的程序非常慢并且使用大量内存。我做了一些分析,我知道大部分时间(~50%)都花在了垃圾收集上。我已经尝试了我能想到的一切来达到我现在所拥有的,包括:
- 以 Data.Map 作为存储的 ST monad 东西
- 使用散列值作为键,而不是保留整个字节串
- 使用 seq 和 deepseq 尝试防止延迟分配
- 逐行解析,而不是希望懒惰可以使解析行列表节省空间和时间
- 使用不可变哈希图而不是 Data.Map
- 使用可变哈希图
代码、数据、分析输出和编译的东西:https://gist.github.com/ririw/8205284
谢谢!
【问题讨论】:
-
这些行对我来说看起来很可疑:
let parsed = parseOnly linkLineParser line in parsed 'par' case (parseOnly linkLineParser line) of,您应该将其更改为更像 popAbstract 的情况已结束parsed。我认为您正在对 NTEntries 进行全面评估。 (所以 cmets 不让我很好地格式化它) -
啊,很好,我想我改变了抽象的,忘了做链接。但这仍然不能解决问题。我认为我错过了一些关于内存分配如何工作或我应该如何处理数据的根本重要部分,这可能会阻止 GC 不得不移动这么多。
-
虽然我无法在性能方面为您提供帮助,但我可以推荐 hackage.haskell.org/package/swish-0.9.0.11/docs/… 以便于解析
-
令我惊讶的是
resourceName完成了 27% 的分配。有趣的是,当我运行程序时,link也完成了 23% 的分配。分析器的输出是否与 gist 中编写的程序完全一致?否则我不明白区别。无论如何,似乎takeWhile和skipWhile做了很多分配。也许attoparsec或bytestring专家可以提供帮助。 -
我想我一定是不小心启动了旧的分析器运行。我通过从使用
(.*>) :: ByteString -> Parser a -> Parser a切换到使用string :: ByteString -> Parser ByteString解决了这个问题。
标签: haskell memory-management garbage-collection