【发布时间】:2026-01-26 01:00:02
【问题描述】:
对以下内容进行基准测试:
#!/usr/bin/env stack
-- stack --resolver lts-16.2 script --package async --package criterion
import Control.Concurrent.Async (async, replicateConcurrently_)
import Control.Monad (replicateM_, void)
import Criterion.Main
main :: IO ()
main = defaultMain [
bgroup "tests" [ bench "sync" $ nfIO syncTest
, bench "async" $ nfIO asyncTest
]
]
syncTest :: IO ()
syncTest = replicateM_ 100000 dummy
asyncTest :: IO ()
asyncTest = replicateConcurrently_ 100000 dummy
dummy :: IO Int
dummy = return $ fib 10000000000
fib :: Int -> Int
fib 0 = 1
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)
给我这个:
% ./applicative-v-monad.hs
benchmarking tests/sync
time 2.120 ms (2.075 ms .. 2.160 ms)
0.997 R² (0.994 R² .. 0.999 R²)
mean 2.040 ms (2.023 ms .. 2.073 ms)
std dev 77.37 μs (54.96 μs .. 122.8 μs)
variance introduced by outliers: 23% (moderately inflated)
benchmarking tests/async
time 475.3 ms (310.7 ms .. 642.8 ms)
0.984 R² (0.943 R² .. 1.000 R²)
mean 527.2 ms (497.9 ms .. 570.9 ms)
std dev 41.30 ms (4.833 ms .. 52.83 ms)
variance introduced by outliers: 21% (moderately inflated)
很明显 asyncTest 运行时间比 syncTest 长。
我原以为并发运行昂贵的操作会比按顺序运行更快。我的推理有问题吗?
【问题讨论】:
-
没有时间写出正确的答案,但如果正在评估 fib 10000000000,它将需要 2^10000000000 步,而不是几毫秒。你的测试都没有强迫它。
标签: haskell concurrency benchmarking io-monad criterion