使用大数据进行微基准测试

3
我目前正在设计一个缓存实现,用于与最短路径图算法一起使用的论文项目。该图算法的运行时间相当不一致,因此对整个算法进行基准测试太麻烦了。我必须专注于仅基准测试缓存。
我需要基准测试的缓存大约有十几种Map接口的实现。这些缓存旨在与给定的访问模式(从上述算法中查询键的顺序)良好地配合使用。但是,在“小”问题的运行中,会有数百亿个查询。我需要运行几乎所有的查询才能对基准测试结果有信心。
我在如何将数据加载到内存中方面遇到了概念性问题。可以创建一个查询日志,它只是一个按照顺序排列的所有查询键的磁盘上的列表(它们是10个字符的字符串标识符),这些查询键在算法的一个运行中被查询。这个文件非常大。我想到的另一个想法是将日志分成1-5百万个查询的块,并按以下方式进行基准测试:
  1. 加载1-5百万个键
  2. 将开始时间设置为当前时间
  3. 按顺序查询它们
  4. 记录经过的时间(当前时间-开始时间)
我不确定这会对缓存产生什么影响。如何执行热身期?加载文件可能会清除上一个块的L1或L2缓存中的任何数据。此外,维护一个1-5百万个元素的字符串数组有什么影响(甚至迭代它是否会扭曲结果)?
记住访问模式很重要!例如,有一些具有移动到前启发式的哈希表,可以重新排序表的内部结构。多次运行单个块或无序地运行块是不正确的。这使得预热CPU缓存和HotSpot变得更加困难(我还可以保留一个用于预热但不计时的辅助虚拟缓存)。
如何在巨大的数据集上进行微基准测试的良好实践是什么?

2
那不是一个"微基准测试",而是一个"宏基准测试"。 - Louis Wasserman
1
但它正在对单个操作进行基准测试 - 哈希表查找。 - efritz
如果你要测量毫秒,不要使用System.currentTimeMillis,而应该使用System.nanoTime()System.currentTimeMillis vs System.nanoTime - Luiggi Mendoza
如果您只是在对一系列单个操作进行基准测试,那么您可能可以使用Caliper,并按指定顺序运行reps,在setUp()中初始化所有内容。话虽如此,即使仅仅加载数据的成本也比我见过的任何Caliper微基准测试都要高...所以,呃。 - Louis Wasserman
@efritz 你可以使用10GB的内存缓存10GB的数据。真正占用空间的是你对它的处理方式(16GB的内存现在只需花费80美元,所以这并不算多)。 - Peter Lawrey
显示剩余5条评论
1个回答

1
如果我正确理解问题的话,您可以将查询日志加载到一台机器上,如果内存不足,可以分块加载,并通过专用网络(可能是交叉线缆)将其流式传输到运行基准测试的机器上,以便在测试系统和测试代码/数据之间最小化干扰...?
无论使用什么解决方案,都应该尝试多次运行,以便评估可重复性-如果您没有得到合理的可重复性,那么您至少可以检测出您的解决方案不适用!
更新:关于分批和计时-实际上,您可能最终会采用某种形式的细粒度分批,以便有效地将数据传输到网络。如果您的数据属于自然大型“组”或阶段,则我会单独计时这些数据以检查异常情况,但最强烈依赖整体计时。我认为计时数千个小批次没有太多好处(考虑到您正在处理数百万个批次)。
即使您在一台具有大量RAM的机器上运行所有内容,也可能值得将数据加载到一个JVM中,将待测试的代码加载到另一个JVM中,以便缓存JVM上的垃圾收集不受需要保存查询日志的大堆的直接影响。

如果您使用网络,您是逐个执行关键查找,还是应该将它们分批进行,每批包含10,000或1,000,000个查找?在任何情况下,您会计时多少(所有内容或查找组)? - efritz
作为参考,读取文件大约占运行测试所需时间的80-90%(包括读取文件、创建测试数组和执行所有查找)。 - efritz
在这种情况下,看起来值得投资足够的RAM来一次性加载数据集,然后将其提供给多个候选者。 - DNA
我台式电脑有16GB的RAM,但我担心的是文件加载速度(以及任何缓存影响)。 - efritz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接