2015-10-18 103 views
12

最近,在我的項目上運行基準測試後,我發現嚴格字節串的直接構建可能比涉及構建器的構造快一個數量級。高效創建嚴格的ByteString

例如,編碼器實現,它採用的助洗劑:

encoder :: Int64 -> Data.ByteString.ByteString 
encoder = 
    Data.ByteString.Lazy.toStrict . 
    Data.ByteString.Builder.toLazyByteString . 
    Data.ByteString.Builder.int64BE 

執行像一個比,這直接構建字節串,並且具有用於進一步優化幾種可能性差10倍:

encoder :: Int64 -> Data.ByteString.ByteString 
encoder = 
    unpackIntBySize 8 

unpackIntBySize :: (Bits a, Integral a) => Int -> a -> Data.ByteString.ByteString 
unpackIntBySize n x = 
    Data.ByteString.pack $ map f $ reverse [0..n - 1] 
    where 
    f s = 
     fromIntegral $ shiftR x (8 * s) 

所以我的問題是兩方面的:

  1. 瓦y是否沒有直接從Builder轉換爲嚴格ByteString?這很煩人,因爲我經常必須導入Data.ByteString.Lazy只是爲了使用toStrict函數,因爲Data.ByteString.Builder只公開toLazyByteString

  2. 但是,上述經驗讓我懷疑,如果它不是有原因的。原因是我完全應用了不正確的使用模式。那麼,這確實是不正確的,是否有更好的選擇?順便說一句,我知道Data.ByteString.Builder.Prim,但我懷疑在上述情況下使用它會產生很大的差異。

+0

有趣。對於我的日常工作,我假設builder - > lazy ByteString - > strict Bytestring的方式在從大量短字符串中構建一個大字符串時只會付出代價。我通常會打包。顯示從數字轉換爲嚴格的bs ...不知道它是否好。你可以發佈一些可用於衡量性能的代碼嗎?這看起來像一個有趣的問題。 – dsign

+0

「postgresql-binary」項目有兩個分支,它們使用兩種不同的策略實現編碼器。兩者都具有編碼性能的基準。這是[一棵樹,其中的編碼器是通過直接的'ByteString'構造實現的](https://github.com/nikita-volkov/postgresql-binary/tree/911a32110cfd618e2f7d377f4acc4c8f593f9acc),這裏是[圍繞'Builder'旋轉的那個] (https://github.com/nikita-volkov/postgresql-binary/tree/2fb6954968763621cbbdb8ba8505434ec2961b9e)。 –

+1

我覺得麻煩的是'Builder'不保持寫出結果字節串所需的字節數,儘管當你沒有做懶惰流時,這是靜態已知的(O(1))或O( N) - 丁大概價值 - 它。你可以看看'buffer-builder',看看它是否滿足你的需求。請參閱此處的討論:https://github.com/chadaustin/buffer-builder/issues/7 – jberryman

回答

7

構建器不是一個零成本的抽象,它針對大型惰性字符串進行了優化。從建設者docs

目前的實現是4KB和32KB

之間進行調整,平均塊大小根據你的情況,建設者分配整個4K塊只產生8個字節。

pack比較,它計算必要的緩衝區大小,分配它,然後在循環中填充它。低效率的唯一來源是預先分配的8 Word8的清單。可能unfoldrN會更有效率。

使用構建器構造小的嚴格字節串有時很方便,但有更好的方法。

+0

謝謝!你提到「更好的方法」。你意味着什麼?有沒有你會建議的圖書館? –

+0

@NikitaVolkov我認爲更好的表現特別的方式,比如'unfoldrN'。我不知道任何使生活更輕鬆的特定庫,並且當性能不重要時,我通常使用bytestring構建器。 – Yuras

+0

連接小嚴格字節串怎麼樣?使用'append'和/或'concat'最有效嗎? –

3

嘗試使用toLazyByteStringWith來自Data.ByteString.Builder.Extra來調整您的ByteString構造。這需要AllocationStrategy,它允許您調整緩衝區大小和增長率。