わずかにリファクタリング(基本的に左向き)すると、パフォーマンスが大幅に向上し、8388600バイトのファイルをかなり解析してGCオーバーヘッドが低下します。
{-# LANGUAGE BangPatterns #-}
module Main (main) where
import qualified Data.ByteString.Lazy as BL
import Data.Binary.Get
data Trade = Trade
{ timestamp :: {-# UNPACK #-} !Int
, price :: {-# UNPACK #-} !Int
, qty :: {-# UNPACK #-} !Int
} deriving (Show)
getTrade :: Get Trade
getTrade = do
timestamp <- getWord32le
price <- getWord32le
qty <- getWord16le
return $! Trade (fromIntegral timestamp) (fromIntegral price) (fromIntegral qty)
countTrades :: BL.ByteString -> Int
countTrades input = stepper (0, input) where
stepper (!count, !buffer)
| BL.null buffer = count
| otherwise =
let (trade, rest, _) = runGetState getTrade buffer 0
in stepper (count+1, rest)
main :: IO()
main = do
input <- BL.readFile "trades.bin"
let trades = countTrades input
print trades
関連するランタイム統計情報。割り当て数が近いにもかかわらず、GCと最大ヒープサイズはリビジョン間でかなり異なっています。
ここでのすべての例は、GHC 7.4.1 -O2で構築されています。過度のスタック領域の使用状況に+ RTS -K1G -RTSで実行
元のソース、:
426,003,680 bytes allocated in the heap
443,141,672 bytes copied during GC
99,305,920 bytes maximum residency (9 sample(s))
203 MB total memory in use (0 MB lost due to fragmentation)
Total time 0.62s ( 0.81s elapsed)
%GC time 83.3% (86.4% elapsed)
ダニエルのリビジョン:
357,851,536 bytes allocated in the heap
220,009,088 bytes copied during GC
40,846,168 bytes maximum residency (8 sample(s))
85 MB total memory in use (0 MB lost due to fragmentation)
Total time 0.24s ( 0.28s elapsed)
%GC time 69.1% (71.4% elapsed)
そして、このポスト:
290,725,952 bytes allocated in the heap
109,592 bytes copied during GC
78,704 bytes maximum residency (10 sample(s))
2 MB total memory in use (0 MB lost due to fragmentation)
Total time 0.06s ( 0.07s elapsed)
%GC time 5.0% (6.0% elapsed)
実際の世界ではプロファイリングに関するhaskellの章があり、so.comでは[haskell] + [performance]とタグ付けされたいくつかの質問があります。これはおそらくヨーヨーの助けになりますu。 – epsilonhalbe
@epsilonhalbeありがとうございました。私は良い検索をしていました。このパターンは、Data.Binary.Getのドキュメントの1つです。私はそれが「ほとんどトレイル再帰」の問題だと思うが、それを理解するのは私の外にある。 –
これはData.Binary.Getが厳密に見えるので難しいです - 私はより良い怠惰を得ることについて以前のコメントをしましたが、適用できないので削除しました。ダニエルフィッシャーの答えは、あなたが厳しいより良い仕事をする方法を示しています。 –