【发布时间】:2017-09-18 13:53:16
【问题描述】:
我想知道我的程序将一个 12.9MB .wav 文件读入内存需要多长时间。将文件读入内存的函数如下所示:
import qualified Data.ByteString as BS
getSamplesFromFileAsBS :: FilePath -> IO (BS.ByteString)
它采用文件名并将样本作为ByteString 返回。它还对数据执行一些其他有效性检查并忽略标头信息。我使用ByteString.hGet 将样本的ByteString 读入内存。
如果我现在用一个 12.9MB 的文件对这个函数进行基准测试,使用 Criterion:
bencher :: FilePath -> IO ()
bencher fp = defaultMain [
bench "Reading all the samples from a file." $ nfIO (getSamplesFromFileAsBS fp)
]
我得到以下结果:
benchmarking Reading all the samples from a file.
time 3.617 ms (3.520 ms .. 3.730 ms)
0.989 R² (0.981 R² .. 0.994 R²)
mean 3.760 ms (3.662 ms .. 3.875 ms)
std dev 354.0 μs (259.9 μs .. 552.5 μs)
variance introduced by outliers: 62% (severely inflated)
似乎在 3.617 毫秒内将 12.9MB 加载到内存中。这似乎不太现实,因为它表明我的 SSD 可以读取 3+GB/s,而事实并非如此。我做错了什么?
我决定尝试另一种(更天真的)方法,手动测量时差:
runBenchmarks :: FilePath -> IO ()
runBenchmarks fp = do
start <- getCurrentTime
samplesBS <- getSamplesFromFileAsBS fp
end <- samplesBS `deepseq` getCurrentTime
print (diffUTCTime end start)
这给了我以下结果:0.023105s。这是现实的,因为这意味着我的 SSD 可以以大约 600MB/s 的速度读取。 Criterion 结果有什么问题?
【问题讨论】:
-
"似乎在 3.617ms 内将 12.9MB 加载到内存中。这似乎不太现实,因为这表明我的 SSD 可以读取 3+MB/s,而在全部。” 这似乎不对。 4ms 内的 12MB 将是 3GB/s,而不是 3MB/s。
-
@Zeta 对不起,你是对的。这是一个错字,我更正了。 3GB/s 对于我的 SSD 来说仍然不现实。
-
我想说 3GB/s 是现实的,因为现代操作系统应该为您将文件缓存在内存中。当然,这并不能真正解释您使用 Criterion 获得的差异。
-
第二个基准测试是在冷的 OS FS 缓存上运行的吗?我相信标准将多次运行基准测试并提供足够的可用内存,除了第一次运行之外的任何后续运行都将使用操作系统缓存而不是从磁盘重新读取,这也许可以解释差异。当您调用
runBenchmarks两次/三次时,您会得到什么测量结果? -
@ppb 第二个基准测试没有在冷的 OS FS 缓存上运行。如果我连续多次调用
runBenchmarks,它会变得更快。我现在平均在 10 毫秒左右。我见过的最快的是8ms。也许缓存似乎是原因。
标签: haskell benchmarking criterion