总览
动态编译的好处之一是,它能够支持在虚拟方法代码上进行广泛的方法内联。
虽然内联代码可以提高性能,但是代码仍然必须检查类型(以防由于优化而更改了类型)或在多个可能的实现之间进行选择。
这导致了问题。 通过接口调用的方法的多个实现如何影响性能。
标杆管理
此基准测试了作为列表元素调用的简单方法。 它比较列表中不同类的数量以查看其性能,但还改变了展开循环的数量,从而减少了可能的类数量。 例如,对于一个12个不同类的列表,以重复的方式,在不展开的情况下,方法调用可能是12个类中的任何一个,但是当循环展开到两个程度时,每个调用只有6个可能的类(12 / 2)。 展开为三个级别时,每个调用有12个(4/3)个可能的类,对于展开为六个级别的循环,只有两个可能的类。 注意:每行代码可能的类都不相同。
这些是2.5 GHz i5上的结果。 时间以纳秒为单位。 轴标题是指从给定代码行使用或调用的不同类的数量。
1二手 | 2二手 | 3二手 | 4二手 | 6二手 | 8二手 | 12使用 | |
每个呼叫站点1个 | 48.4 | 46.6 | 46.9 | 43.7 | 48.7 | 54.9 | |
每个呼叫站点2个 | 115.8 | 80.5 | 92.8 | 87 | 112 | ||
每个呼叫站点3个 | 285 | 283 | 271 | ||||
每个呼叫站点4个 | 669 | 281 | 275 | ||||
每个呼叫站点6个 | 562 | 275 | |||||
每个呼叫站点8个 | 498 | ||||||
每个呼叫站点12个 | 530 |
看起来,加载的类的数量,甚至列表中的类的数量,都不如从给定代码段调用的可能的类的数量重要。 同样,可以循环地优化同一循环中的不同代码段。
您会看到,如果给定调用只能创建一个可能的类,则程序中使用的类数无关紧要。
另一个含义是,如果要通过一个公共接口比较两个替代方案,则必须小心如何运行测试,这样就不会因为只使用一种类型的事实而偏爱第一次运行。 为了解决这个问题,我建议; 多次运行所有测试,总共至少2秒钟。 这样可以减少与您执行测试的顺序相关的bais。
参考:来自Vanilla Java博客的JCG合作伙伴 Peter Lawrey 在Java中内联虚拟方法调用的性能 。
翻译自: https://www.javacodegeeks.com/2012/12/performance-of-inlined-virtual-method-invocations-in-java.html