最近,在我的项目上运行基准测试后,我发现严格字节串的直接构建可能比涉及构建器的构造快一个数量级。高效创建严格的ByteString
例如,编码器实现,它采用的助洗剂:
encoder :: Int64 -> Data.ByteString.ByteString
encoder =
Data.ByteString.Lazy.toStrict .
Data.ByteString.Builder.toLazyByteString .
Data.ByteString.Builder.int64BE
执行像一个比,这直接构建字节串,并且具有用于进一步优化几种可能性差10倍:
encoder :: Int64 -> Data.ByteString.ByteString
encoder =
unpackIntBySize 8
unpackIntBySize :: (Bits a, Integral a) => Int -> a -> Data.ByteString.ByteString
unpackIntBySize n x =
Data.ByteString.pack $ map f $ reverse [0..n - 1]
where
f s =
fromIntegral $ shiftR x (8 * s)
所以我的问题是两方面的:
瓦y是否没有直接从
Builder
转换为严格ByteString
?这很烦人,因为我经常必须导入Data.ByteString.Lazy
只是为了使用toStrict
函数,因为Data.ByteString.Builder
只公开toLazyByteString
。但是,上述经验让我怀疑,如果它不是有原因的。原因是我完全应用了不正确的使用模式。那么,这确实是不正确的,是否有更好的选择?顺便说一句,我知道
Data.ByteString.Builder.Prim
,但我怀疑在上述情况下使用它会产生很大的差异。
有趣。对于我的日常工作,我假设builder - > lazy ByteString - > strict Bytestring的方式在从大量短字符串中构建一个大字符串时只会付出代价。我通常会打包。显示从数字转换为严格的bs ...不知道它是否好。你可以发布一些可用于衡量性能的代码吗?这看起来像一个有趣的问题。 – dsign
“postgresql-binary”项目有两个分支,它们使用两种不同的策略实现编码器。两者都具有编码性能的基准。这是[一棵树,其中的编码器是通过直接的'ByteString'构造实现的](https://github.com/nikita-volkov/postgresql-binary/tree/911a32110cfd618e2f7d377f4acc4c8f593f9acc),这里是[围绕'Builder'旋转的那个] (https://github.com/nikita-volkov/postgresql-binary/tree/2fb6954968763621cbbdb8ba8505434ec2961b9e)。 –
我觉得麻烦的是'Builder'不保持写出结果字节串所需的字节数,尽管当你没有做懒惰流时,这是静态已知的(O(1))或O( N) - 丁大概价值 - 它。你可以看看'buffer-builder',看看它是否满足你的需求。请参阅此处的讨论:https://github.com/chadaustin/buffer-builder/issues/7 – jberryman