高效地将字节串转换为[Word16]

3

我正在尝试将一个字节串转换为Word16s列表。下面使用Data.Binary.Get的实现可以工作,但它是代码中的性能瓶颈。这是可以理解的,因为IO总是会很慢,但我想知道是否有更有效的方法来做到这一点。

getImageData' = do
    e <- isEmpty
    if e then return []
      else do
      w <- getWord16be
      ws <- getImageData'
      return $ w : ws

2
这里没有IO。反序列化及其性能是我在Haskell中遇到的第一个烦恼。你可以查看pureMD5包和32位反序列化方法。 - Thomas M. DuBuisson
1个回答

2
我猜测你在使用Data.Binary.Get时遇到的主要问题是解码器本质上对你的目的来说太严格了。这似乎也适用于serialise和其他序列化库。我认为根本的问题在于,虽然你知道只要ByteString具有偶数个字节,操作就会成功,但库不知道这一点。因此,在构建你请求的列表之前,它必须读取整个ByteString才能得出“啊哈,一切正常”的结论。实际上,按照你构建结果的方式,它将在实际执行任何有用操作之前构建一堆闭包(数量与长度成比例)。
如何解决这个问题?直接使用bytestring库即可。最简单的方法是使用unpack,但我认为你可能会像这样获得稍微更好的性能:
{-# language BangPatterns #-}
module Wordy where
import qualified Data.ByteString as BS
import Data.ByteString (ByteString)
import Data.Word (Word16)
import Data.Maybe (fromMaybe)
import Data.Bits (unsafeShiftL)

toDBs :: ByteString -> Maybe [Word16]
toDBs bs0
  | odd (BS.length bs0) = Nothing
  | otherwise = Just (go bs0)
  where
    go bs = fromMaybe [] $ do
      (b1, bs') <- BS.uncons bs
      (b2, bs'') <- BS.uncons bs'
      let !res = (fromIntegral b1 `unsafeShiftL` 8) + fromIntegral b2
      Just (res : go bs'')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接