ここに完全なリポジトリがあります。これは非常に単純なテストで、postgresql-simple データベース バインディングを使用して 50000 個のランダムなものをデータベースに挿入します。MonadRandom を使用し、遅延して Thing を生成できます。
ケース 1と Thing ジェネレーターを使用した特定のコード スニペットを次に示します。
insertThings c = do
ts <- genThings
withTransaction c $ do
executeMany c "insert into things (a, b, c) values (?, ?, ?)" $ map (\(Thing ta tb tc) -> (ta, tb, tc)) $ take 50000 ts
これは case2で、Things を stdout にダンプするだけです。
main = do
ts <- genThings
mapM print $ take 50000 ts
最初のケースでは、GC 時間が非常に悪いです。
cabal-dev/bin/posttest +RTS -s
1,750,661,104 bytes allocated in the heap
619,896,664 bytes copied during GC
92,560,976 bytes maximum residency (10 sample(s))
990,512 bytes maximum slop
239 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 3323 colls, 0 par 11.01s 11.46s 0.0034s 0.0076s
Gen 1 10 colls, 0 par 0.74s 0.77s 0.0769s 0.2920s
INIT time 0.00s ( 0.00s elapsed)
MUT time 2.97s ( 3.86s elapsed)
GC time 11.75s ( 12.23s elapsed)
RP time 0.00s ( 0.00s elapsed)
PROF time 0.00s ( 0.00s elapsed)
EXIT time 0.00s ( 0.00s elapsed)
Total time 14.72s ( 16.09s elapsed)
%GC time 79.8% (76.0% elapsed)
Alloc rate 588,550,530 bytes per MUT second
Productivity 20.2% of total user, 18.5% of total elapsed
2番目のケースでは時間は素晴らしいですが:
cabal-dev/bin/dumptest +RTS -s > out
1,492,068,768 bytes allocated in the heap
7,941,456 bytes copied during GC
2,054,008 bytes maximum residency (3 sample(s))
70,656 bytes maximum slop
6 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 2888 colls, 0 par 0.13s 0.16s 0.0001s 0.0089s
Gen 1 3 colls, 0 par 0.01s 0.01s 0.0020s 0.0043s
INIT time 0.00s ( 0.00s elapsed)
MUT time 2.00s ( 2.37s elapsed)
GC time 0.14s ( 0.16s elapsed)
RP time 0.00s ( 0.00s elapsed)
PROF time 0.00s ( 0.00s elapsed)
EXIT time 0.00s ( 0.00s elapsed)
Total time 2.14s ( 2.53s elapsed)
%GC time 6.5% (6.4% elapsed)
Alloc rate 744,750,084 bytes per MUT second
Productivity 93.5% of total user, 79.0% of total elapsed
ヒープ プロファイリングを適用しようとしましたが、何もわかりませんでした。50000 個のすべての Thing が最初にメモリ内に構築され、次にクエリで ByteStrings に変換され、これらの文字列がデータベースに送信されるようです。しかし、なぜそれが起こるのですか?有罪コードはどのように判断するのですか?
GHC のバージョンは 7.4.2 です
すべてのライブラリとパッケージ自体のコンパイル フラグは -O2 です (サンドボックスで cabal-dev によってコンパイルされます)。