严格字节串的有效管道分块

Efficient chunking of conduit for strict bytestring

这是 earlier question 的后续。我有一个管道来源(来自 Network.HTTP.Conduit),它是严格的 ByteString。我想将它们重新组合成更大的块(在另一个编码和转换为惰性字节串之后通过网络发送到另一个客户端)。我写了 chunksOfAtLeast 管道,从上述问题的答案中得出,它似乎工作得很好。我想知道是否还有进一步提高性能的余地。

import Data.Conduit as C
import Control.Monad.IO.Class
import Control.Monad
import Data.Conduit.Combinators as CC
import Data.Conduit.List as CL
import Data.ByteString.Lazy as LBS hiding (putStrLn)
import Data.ByteString as BS hiding (putStrLn)

chunksOfAtLeast :: Monad m => Int -> Conduit BS.ByteString m BS.ByteString
chunksOfAtLeast chunkSize =
    loop
  where
    loop = do
        bs <- takeE chunkSize =$= ((BS.concat . ($ [])) <$> CL.fold (\front next -> front . (next:)) id)
        unless (BS.null bs) $ do
            yield bs
            loop

main = do
  yieldMany ["hello", "there", "world!"] $$ chunksOfAtLeast 8 =$ CL.mapM_ Prelude.print

获得最佳性能总是需要尝试一些东西并对其进行基准测试,所以我不能肯定地告诉你我正在为你提供更有效的东西。也就是说,将较小的数据块组合成较大的块是 builders 的主要目标,因此利用它们可能更有效。这是一个例子:

{-# LANGUAGE OverloadedStrings #-}
import Conduit
import Data.ByteString (ByteString)
import Data.ByteString.Builder (byteString)
import Data.Conduit.ByteString.Builder

bufferChunks :: Conduit ByteString IO ByteString
bufferChunks = mapC byteString =$= builderToByteString

main :: IO ()
main = yieldMany ["hello", "there", "world!"] $$ bufferChunks =$ mapM_C print