Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficient Conversion of Bytestring to [Word16]

I am attempting to do a plain conversion from a bytestring to a list of Word16s. The implementation below using Data.Binary.Get works, though it is a performance bottleneck in the code. 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.

getImageData' = do
    e <- isEmpty
    if e then return []
      else do
      w <- getWord16be
      ws <- getImageData'
      return $ w : ws
like image 704
Dylan B. Avatar asked Dec 06 '25 18:12

Dylan B.


1 Answers

I suspect the big problem you're encountering with Data.Binary.Get is that the decoders are inherently much too strict for your purpose. This also appears to be the case for serialise, and probably also the other serialization libraries. 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. 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. 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. The easiest thing is to use unpack, but I think you'll probably get slightly better performance like this:

{-# 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'')
like image 107
dfeuer Avatar answered Dec 08 '25 20:12

dfeuer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!