我如何写一个正确的微观

你如何在Java中编写(并运行)一个正确的微基准测试?

我正在寻找代码示例和评论来说明各种需要考虑的事情。

例如:基准应该测量时间/迭代还是迭代/时间,为什么?

相关:秒表基准测试是否可以接受?


关于从Java HotSpot的创建者编写微型基准测试的技巧:

规则0:在JVM上读取一份有信誉的论文并进行微观基准测试。 Brian Goetz,2005年是一个不错的选择。不要对微基准期望太高, 它们仅测量有限范围的JVM性能特征。

规则1:始终包含一个预热阶段,该阶段一直运行您的测试内核,足以在定时阶段之前触发所有初始化和编译。 (预热阶段的迭代次数较少,经验法则是数万次内循环迭代。)

规则2:始终使用-XX:+PrintCompilation-verbose:gc等运行,这样您就可以验证编译器和JVM的其他部分在计时阶段没有做出意外的工作。

规则2.1:在定时和预热阶段的开始和结束时打印消息,以便您可以在定时阶段验证规则2没有输出。

规则3:注意-client和-server与OSR和常规编译之间的区别。 -XX:+PrintCompilation标志报告带有符号的OSR编译以表示非初始入口点,例如: Trouble$1::run @ 2 (41 bytes) 。 如果您的性能达到最佳状态,则优先选择服务器到客户端,并定期到OSR。

规则4:了解初始化效果。 自打印加载并初始化课程以来,不要在计时阶段首次打印。 不要在加热阶段(或最终报告阶段)之外加载新类,除非您专门测试类加载(并且在这种情况下只加载测试类)。 规则2是你抵抗这种影响的第一道防线。

规则5:注意去最佳化和重新编译的效果。 不要在时序阶段首次采用任何代码路径,因为编译器可能会垃圾并重新编译代码,这是基于之前乐观的假设,即根本不会使用该路径。 规则2是你抵抗这种影响的第一道防线。

规则6:使用适当的工具来阅读编译器的思想,并期望它会产生的代码感到惊讶。 在形成更快或更慢的东西的理论之前,亲自检查代码。

规则7:减少测量中的噪音。 在一台安静的机器上运行你的基准测试,并运行几次,丢弃异常值。 使用-Xbatch将编译器与应用程序序列化,并考虑设置-XX:CICompilerCount=1以防止编译器与自身并行运行。

规则8:为您的基准测试使用库,因为它可能更高效,并且已经为此唯一目的进行了调试。 如JMH,Caliper或Bill和Paul的Java优秀UCSD基准测试。


我知道这个问题已被标记为答案,但我想提两个库,使我们能够编写微基准

来自Google的Caliper

入门教程

  • http://codingjunkie.net/micro-benchmarking-with-caliper/
  • http://vertexlabs.co.uk/blog/caliper
  • 来自OpenJDK的JMH

    入门教程

  • 避免在JVM上进行标杆管理
  • http://nitschinger.at/Using-JMH-for-Java-Microbenchmarking
  • http://java-performance.info/jmh/

  • Java基准测试的重要内容是:

  • 在对它进行计时之前,先多次运行代码,以此来预热JIT
  • 确保你运行足够长的时间,以便能够在几秒或更好的几十秒内测量结果
  • 尽管在迭代之间不能调用System.gc() ,但在测试之间运行它是一个好主意,这样每个测试都有望获得一个“干净”的内存空间。 (是的, gc()更像是一种暗示,而非保证,但很可能它真的会在我的经验中被垃圾收集。)
  • 我喜欢展示迭代和时间,以及可以缩放的时间/迭代分数,以使得“最佳”算法得分1.0,而其他得分以相对方式得分。 这意味着您可以长时间运行所有算法,改变迭代次数和时间,但仍可获得可比较的结果。
  • 我只是在写关于.NET基准框架设计的博客。 我有几个较早的帖子,可能会给你一些想法 - 当然不是所有的都适合,但有些可能会。

    链接地址: http://www.djcxy.com/p/2479.html

    上一篇: How do I write a correct micro

    下一篇: How malloc allocates memory and what is the size of Heap?