简体   繁体   English

字节串的有效转换为[Word16]

[英]Efficient Conversion of Bytestring to [Word16]

I am attempting to do a plain conversion from a bytestring to a list of Word16s. 我试图从字节字符串到Word16s列表进行简单转换。 The implementation below using Data.Binary.Get works, though it is a performance bottleneck in the code. 下面使用Data.Binary.Get的实现可行,但它是代码中的性能瓶颈。 This is understandable as IO is always going to be slow, but I was wondering if there isn't a more efficient way of doing this. 这是可以理解的,因为IO总是很慢,但我想知道是否有更有效的方法来做到这一点。

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

I suspect the big problem you're encountering with Data.Binary.Get is that the decoders are inherently much too strict for your purpose. 我怀疑你遇到的与Data.Binary.Get有关的一个大问题是,解码器本质上对你的目的太严格了。 This also appears to be the case for serialise , and probably also the other serialization libraries. 这似乎也适用于serialise ,也可能是其他序列化库。 I think the fundamental trouble is that while you know that the operation will succeed as long as the ByteString has an even number of bytes, the library does not know that. 我认为根本的问题在于,只要ByteString具有偶数个字节, 您就知道操作会成功,但是库不知道。 So it has to read in the whole ByteString before it can conclude "Ah yes, all is well" and construct the list you've requested. 所以它必须在整个ByteString读取它才能得出结论“啊是的,一切都很好”并构建你所请求的列表。 Indeed, the way you're building the result, it's going to build a slew of closures (proportional in number to the length) before actually doing anything useful. 实际上,在构建结果的过程中,它会在实际执行任何有用的操作之前构建一系列闭包(数量与长度成比例)。

How can you fix this? 你怎么解决这个问题? Just use the bytestring library directly. 只需直接使用bytestring库。 The easiest thing is to use unpack , but I think you'll probably get slightly better performance like this: 最简单的方法是使用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'')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM