深入拆解 Java 虚拟机
郑雨迪
Oracle 高级研究员,计算机博士
87446 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 40 讲
模块四:黑科技 (3讲)
深入拆解 Java 虚拟机
15
15
1.0x
00:00/00:00
登录|注册

28 | 基准测试框架JMH(上)

通过注解处理器自动生成性能测试代码
JMH内置功能和策略规避影响
性能测试存在深坑,JMH是解决方案之一
运行jar包进行性能测试
生成的class文件打包成jar包
利用注解处理器自动生成性能测试的代码
生成的项目包含pom.xml文件和测试文件
使用maven archetype生成预设好依赖关系的maven项目模板
提供策略降低操作系统和硬件系统的影响
内置功能控制即时编译器的优化
针对纳秒级别、微秒级别、毫秒级别和秒级别的性能测试
面向Java语言的性能基准测试框架
电源管理策略、CPU缓存、分支预测器、超线程技术对测试结果的影响
循环优化导致数据偏差
混杂了解释执行和即时编译生成代码的测量方式
忽略了Java虚拟机、操作系统和硬件系统的影响
不严谨的性能测试
总结与实践
JMH项目编译和运行
JMH项目生成
JMH介绍
性能基准测试的问题
性能基准测试框架JMH

该思维导图由 AI 生成,仅供参考

今天我们来聊聊性能基准测试(benchmarking)。
大家或许都看到过一些不严谨的性能测试,以及基于这些测试结果得出的令人匪夷所思的结论。
static int foo() {
int i = 0;
while (i < 1_000_000_000) {
i++;
}
return i;
}
举个例子,上面这段代码中的foo方法,将进行 10^9 次加法操作及跳转操作。
不少开发人员,包括我在介绍反射调用那一篇中所做的性能测试,都使用了下面这段代码的测量方式,即通过System.nanoTime或者System.currentTimeMillis来测量每若干个操作(如连续调用 1000 次foo方法)所花费的时间。
public class LoopPerformanceTest {
static int foo() { ... }
public static void main(String[] args) {
// warmup
for (int i = 0; i < 20_000; i++) {
foo();
}
// measurement
long current = System.nanoTime();
for (int i = 1; i <= 10_000; i++) {
foo();
if (i % 1000 == 0) {
long temp = System.nanoTime();
System.out.println(temp - current);
current = System.nanoTime();
}
}
}
}
这种测量方式实际上过于理性化,忽略了 Java 虚拟机、操作系统,乃至硬件系统所带来的影响。

性能测试的坑

关于 Java 虚拟机所带来的影响,我们在前面的篇章中已经介绍过不少,如 Java 虚拟机堆空间的自适配,即时编译等。
在上面这段代码中,真正进行测试的代码(即// measurement后的代码)由于循环次数不多,属于冷循环,没有能触发 OSR 编译。
也就是说,我们会在main方法中解释执行,然后调用foo方法即时编译生成的机器码中。这种混杂了解释执行以及即时编译生成代码的测量方式,其得到的数据含义不明。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文介绍了基准测试框架JMH的重要性以及其在性能基准测试中的作用。传统性能测试方法存在局限性,忽略了Java虚拟机、操作系统和硬件系统对性能测试结果的影响。作者详细讨论了性能测试中的各种坑,包括即时编译器的循环优化、操作系统的电源管理策略、CPU缓存、分支预测器和超线程技术等因素对测试结果的影响。随后,介绍了JMH作为一个面向Java语言的性能基准测试框架,能够控制即时编译器的优化,并提供策略来降低其他影响性能评测的因素。最后,提醒读者不要轻信JMH的性能测试数据,而是需要经过严格论证才能得出通用结论。整体而言,本文通过对性能测试的局限性和JMH的作用进行了深入探讨,为读者提供了对性能基准测试框架JMH的全面了解。 JMH的使用方式并不复杂,可以通过maven生成预设好依赖关系的maven项目模板。通过JMH的注解处理器自动生成性能测试的代码,以及相应的性能测试配置文件。文章最后提到了JMH的实践环节,鼓励读者生成一个JMH项目,并在测试方法中填入自己的业务逻辑。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入拆解 Java 虚拟机》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(5)

  • 最新
  • 精选
  • shitao
    这篇还没留言啊,总结下自己的一点jmh测试经验吧,希望老师指导。 1. 最好在专门的机器上做测试而不是自己的pc 2. 依赖的外部资源如redis,db等,测试过程中最好是独占的 3. 测试时间不宜过短,我一般10min以上吧
    2018-12-26
    18
  • 静心
    老师,什么叫冷循环呀? 既然有冷循环,是不是还有什么所谓的热循环?
    2020-03-19
    1
    2
  • 史海洋
    <dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.3.2</version> </dependency>
    2021-06-28
  • 曾轼麟
    感觉基准测试好麻烦,能否有更加简洁的方式呢?比较真实项目中,依赖还是比较强的
    2021-03-29
  • akka
    自己测试时的一点不同点: java版本:java version "11.0.3" 2019-04-16 LTS; 需提供额外jar包:javax.annotation.javax.annotation-api,否则提示文件缺失; 原@Benchmark包中未提供,自动生成以@GenerateMicroBenchmark替代; mvn package会生成两个jar:microbenchmarks.jar/test-1.21.jar
    2019-05-27
收起评论
显示
设置
留言
5
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部