Java认为java.reflect API的性能成本很高。 旧的Java版本有很大的性能开销,但新版本似乎在可接受的范围内。 但是,“可以接受”是什么意思呢?
这是在评论建议将基于反射的代码替换为标准代码的性能评估时出现的问题。 我们的决策大多基于信念而不是事实,所以我们决定运行一些测试以获得Java8指标。
测试协议
为了在不受挑战的协议中获得实际测量,我们使用了一个很好的JMH测试框架。 JMH的优点包括:
Maven已经存在
您只需使用@benchmark进行评论即可进行基准测试
处理JVM的预热
它还处理将结果写入控制台的操作
以下是JMH片段:
@Benchmark
publicvoidexecuteperformancetest (
//Code goes here
}
JMH负责执行上述executePerformanceTest ()和测量所需时间。
反射码
为了强调反射的成本,让我们研究一下使用反射访问属性和调用简单getter方法而不使用反射时的时间之间的差异。
//With reflection
field first name=clazz.getdeclaredfield (' first name );
field last name=clazz.getdeclaredfield (' last name );
field birth date=clazz.getdeclaredfield (' birth date );
field.set accessible (newaccessibleobject [ ] { first name,lastName,birthDate },true;
firstname.get(Person;
lastname.get(Person );
birthdate.get(Person;
//Without reflection
person.getFirstName (;
person.getLastName (;
person.getBirthDate (;
检查可能的优化
我想知道是否将不变的数据结构编译成优化的字节码以降低反射性能开销。
因此,我们用两种不同的方法创建了相同的基本数据结构。
具有无参数构造函数和setter的变量
具有最终属性和构造函数初始化的不变
反射结果
在我的机器上运行测试,会得到以下结果。
# run complete.total time :00336026336055
benchmarkmodecntscoreerrorunits
benchmark run.runimmutablewithreflectionthrpt 2002492673.50137994.941 ops/s
benchmark run.runimmutablewithoutreflectionthrpt 2002649946.587242499.198 ops/s
benchmark run.runmutablewithreflectionthrpt 2002505239.27727697.028 ops/s
benchmark run.runmutablewithoutreflectionthrpt 20026635097.050150798.911 ops/s
对于对条形图感兴趣的读者,请注意以下事项: (请注意刻度是线性的。