【发布时间】:2014-10-25 00:27:25
【问题描述】:
与@Gabriel Gonzalez 提出的这个问题类似:How to do fast data deserialization in Haskell
我有一个很大的地图,里面有我使用 Cerial 序列化的整数和文本。文件大约10M。
每次我运行我的程序时,我都会反序列化整个事情,这样我就可以查找一些项目。反序列化大约需要 500 毫秒,这没什么大不了的,但我似乎总是喜欢在星期五进行分析。
当我只需要其中的几个时,总是将 100k 反序列化为 1M 似乎很浪费。
我尝试了decodeLazy 并将地图更改为Data.Map.Lazy(不太了解地图如何变得懒惰,但是好的,它就在那里),这对时间没有影响,除非它有点慢。
我想知道是否有一些更智能的东西,只加载和解码必要的东西。当然,像 sqlite 这样的数据库可能非常大,但它只加载完成查询所需的内容。我想找到类似的东西,但不必创建数据库架构。
更新
你知道什么会很棒吗? Mongo 与 Sqlite 的一些融合。就像你可以拥有一个使用平面文件存储的 JSON 文档数据库......当然有人已经在 Ruby 中做到了 https://github.com/hamiltop/MongoLiteDB ... :(
认为 mmap 可能会有所帮助。有史以来第一次尝试了mmap 库和 GHCI 段错误。甚至不知道如何报告该错误。
尝试了bytestring-mmap 库,它可以工作,但没有性能提升。只是替换这个:
ser <- BL.readFile cacheFile
有了这个:
ser <- unsafeMMapFile cacheFile
更新 2
keyvaluehash 可能只是门票。性能似乎真的很好。但是 API 很奇怪,并且缺少文档,因此需要进行一些试验。
更新 3:我是个白痴
显然,我在这里想要的不是更延迟的 Map 反序列化。我想要一个键值对数据库,并且有几个可用的选项,例如 dvm、tokyo-cabinet 和这个我以前从未见过的 levelDB 东西。
Keyvaluehash 看起来是我喜欢的原生 Haskell 键值数据库,但我仍然不知道质量如何。例如,您不能向数据库询问所有键或所有值的列表(唯一真正的操作是readKey、writeKey 和deleteKey),因此如果您需要,则必须将其存储在其他地方。另一个缺点是您必须在创建数据库时告诉它大小。我使用了 20M 的大小,所以我有足够的空间,但它创建的实际数据库占用 266M。不知道为什么,因为没有一行文档。
【问题讨论】:
-
您的问题与 Gabriel 的问题不同(而且更有趣!)。他想要原始速度反序列化整个数据集;您只想解码(也许是读取)需要的内容。我认为您不会找到即插即用的解决方案。假设您想在
Map中查找项目,在没有特别聪明的随机访问反序列化方案的情况下,您是否不必至少反序列化所有密钥? -
我从来没有尝试过这样的事情,但是:使用自定义序列化结构来记录流中的键及其偏移量。然后使用 thunk 将键反序列化为它们的值反序列化器。如果您不想反序列化所有键,则不能使用
Data.Map,并且键查找将更多地涉及流上的二进制搜索或其他内容。你可以使用(记忆的)Key -> Value函数,如果这就是你所需要的。 -
您可以使用
persistent之类的东西,它得到了很好的支持。如果您还没有,请忘记keyvaluehash。它是一个玩具,现在是一个死玩具。
标签: performance haskell serialization deserialization lazy-loading