下面的
byteswap
做了我想要的,但我担心它对于较大的二进制数据 block 来说效率低下。是否有高效的库函数或我可以使用的东西?
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.ByteString as B (ByteString, length, append, cons, foldl)
byteswap :: B.ByteString -> B.ByteString
byteswap = let
swapper (collector, result) byte = let
updated = B.cons byte collector
in if 3 < B.length updated then ("", B.append result updated) else (updated, result)
in snd . B.foldl swapper ("", "")
main = print $ byteswap "1234abcdXYZ"
打印 4321dcba
。
最佳答案
您的代码中较慢的部分是append
,它与您生成的字节串的大小成线性关系,因此您的程序至少需要二次方的时间。
相反,您可以使用列表作为中间结构(理想情况下会被融合掉)并一次性打包整个结果:
byteswap :: B.ByteString -> B.ByteString
byteswap xs = B.pack
[ B.index xs $ i * 4 + j
| i <- [0 .. B.length xs `quot` 4 - 1]
, j <- [3,2,1,0]
]
这可以在我的机器上 3 秒内完成 1000 万字节。
您可以使用不安全的内部字节串函数来加快速度:
byteswap :: B.ByteString -> B.ByteString
byteswap xs = unsafePackLenBytes (B.length xs `quot` 4 * 4)
[ unsafeIndex xs $ i * 4 + j
| i <- [0 .. B.length xs `quot` 4 - 1]
, j <- [3,2,1,0]
]
还有my patch for fusion of unsafePackLenBytes我在 6 毫秒内交换了 1000 万字节。
关于performance - 如何在 Haskell 中有效地字节交换二进制数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71330483/