Criterionで関数をベンチマークする前に、関数の入力の評価を強制するにはどうすればよいですか? いくつかの関数のベンチマークを試みていますが、入力サンクを評価する時間を除外したいと考えています。問題のコードは、入力にボックス化されていないベクトルを使用しますが、これはIntベクトルに対してはディープシーケンスできません。以下のコード スニペットの例:
-- V is Data.Vector.Unboxed
shortv = V.fromList [1..10] :: V.Vector GHC.Int.Int16
intv = V.fromList [1..10] :: V.Vector GHC.Int.Int32
main :: IO ()
main = defaultMain [
bench "encode ShortV" $ whnf encodeInt16V shortv
,bench "encode IntV" $ whnf encodeInt32V intv
]
Criterion ベンチマークには、上記の関数をベンチマークするときのshortvおよびintv入力をビルドする時間が含まれます。基準測定値は以下のとおりです。入力のビルド時間も含まれているように見える各関数で約 400ns を測定します。
benchmarking encode ShortV
mean: 379.6917 ns, lb 378.0229 ns, ub 382.4529 ns, ci 0.950
std dev: 10.79084 ns, lb 7.360444 ns, ub 15.89614 ns, ci 0.950
benchmarking encode IntV
mean: 392.2736 ns, lb 391.2816 ns, ub 393.4853 ns, ci 0.950
std dev: 5.565134 ns, lb 4.694539 ns, ub 6.689224 ns, ci 0.950
ここで、ベンチマーク コードのメイン セクションが次のように変更された場合 (2 番目のベンチ関数を削除することにより):
main = defaultMain [
bench "encode ShortV" $ whnf encodeInt16V shortv
]
encodeInt16V関数がベンチマークされる前に shortv 入力が評価されるようです。このベンチマークは、入力を構築する時間を除いて、関数の実行時間を測定するため、これは私にとって実際に望ましい出力です。以下の基準出力:
benchmarking encode ShortV
mean: 148.8488 ns, lb 148.4714 ns, ub 149.6279 ns, ci 0.950
std dev: 2.658834 ns, lb 1.621119 ns, ub 5.184792 ns, ci 0.950
同様に、"encode IntV" ベンチマークのみをベンチマークすると、そのベンチマークでも最大 150ns の時間が得られます。
Criterion のドキュメントから、より正確なベンチマークのために遅延評価を回避しようとしていることを知っています。それは理にかなっており、ここでは実際の問題ではありません。私の質問は、shortv と intv の入力を作成して、ベンチ関数に渡される前に評価されるようにする方法です。現時点では、defaultMain を制限して一度に 1 つの関数のみをベンチマークすることでこれを実現できますが (上記で示したように)、これは理想的なソリューションではありません。
編集1
ここで Criterion ベンチマークで何か他のことが起こっています。これは、リストではなくベクトル配列でのみ発生するようです。shortv と intv を出力して完全な評価を強制すると、ベンチマークはまだ 150ns ではなく 400ns の時間を測定します。以下のコードの更新:
main = do
V.forM_ shortv $ \x -> do print x
V.forM_ intv $ \x -> do print x
defaultMain [
bench "encode ShortV" $ whnf encodeInt16V shortv
,bench "encode IntV" $ whnf encodeInt32V intv
]
基準出力 (また、正しくないように見える 158.4% の外れ値があります):
estimating clock resolution...
mean is 5.121819 us (160001 iterations)
found 253488 outliers among 159999 samples (158.4%)
126544 (79.1%) low severe
126944 (79.3%) high severe
estimating cost of a clock call...
mean is 47.45021 ns (35 iterations)
found 5 outliers among 35 samples (14.3%)
2 (5.7%) high mild
3 (8.6%) high severe
benchmarking encode ShortV
mean: 382.1599 ns, lb 381.3501 ns, ub 383.0841 ns, ci 0.950
std dev: 4.409181 ns, lb 3.828800 ns, ub 5.216401 ns, ci 0.950
benchmarking encode IntV
mean: 394.0517 ns, lb 392.4718 ns, ub 396.7014 ns, ci 0.950
std dev: 10.20773 ns, lb 7.101707 ns, ub 17.53715 ns, ci 0.950