性能差距是在nextValue()
方法的内联与否上
我自己测试的时候有一个有趣的发现:
使用 OpenJDK 15.0.2 的话,其实 static 与 non-static 性能差距是没有 11.0.2 上那么大的
# 均为5次运行取中位数
# OpenJDK 15.0.2
Cost of static example: 16ms
Cost of non-static example: 3ms
# OpenJDK 14
Cost of static example: 21ms
Cost of non-static example: 3ms
# OpenJDK 11.0.2
Cost of static example: 694ms
Cost of non-static example: 2ms
使用 OpenJDK 15.0.2 进行分析的话,可以看到在 15.0.2 上,Static版本的 nextValue()
和 11.0.2 上一样也是无法内联的。
miigon$ java -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining Main | grep nextValue
34 35 3 StaticExample::nextValue (21 bytes)
34 36 4 StaticExample::nextValue (21 bytes)
35 35 3 StaticExample::nextValue (21 bytes) made not entrant
@ 28 StaticExample::nextValue (21 bytes) not inlineable #这里
@ 28 StaticExample::nextValue (21 bytes) not inlineable
80 121 3 NonStaticExample::nextValue (10 bytes)
80 122 4 NonStaticExample::nextValue (10 bytes)
81 121 3 NonStaticExample::nextValue (10 bytes) made not entrant
@ 47 NonStaticExample::nextValue (10 bytes) inline
@ 47 NonStaticExample::nextValue (10 bytes) inline
不理解 15.0.2 是如何做到不内联也性能差别如此小,个人猜测有可能是:11.0.2 上的 static 版本内不仅 nextValue()
没有内联,或许整个 static 代码块都没有 JIT 编译就执行了,而 15.0.2 上可能有对 static 代码块进行 JIT。不过这个没有 profile 的话也只是猜测。