java – 为什么静态final在每个迭代上比新的慢一些
发布时间:2020-12-14 06:05:28 所属栏目:Java 来源:网络整理
导读:为什么代码片段比代码片段B慢14倍? (在 Windows 7 64位上用jdk1.8.0_60进行测试) 代码段A: import java.awt.geom.RoundRectangle2D;public class Test { private static final RoundRectangle2D.Double RECTANGLE = new RoundRectangle2D.Double(1,2,3,4,5
为什么代码片段比代码片段B慢14倍?
(在 Windows 7 64位上用jdk1.8.0_60进行测试) 代码段A: import java.awt.geom.RoundRectangle2D; public class Test { private static final RoundRectangle2D.Double RECTANGLE = new RoundRectangle2D.Double(1,2,3,4,5,6); public static void main(String[] args) { int result = RECTANGLE.hashCode(); long start = System.nanoTime(); for (int i = 0; i < 100_000_000; i++) { result += RECTANGLE.hashCode(); // <= Only change is on this line } System.out.println((System.nanoTime() - start) / 1_000_000); System.out.println(result); } } 代码段B: import java.awt.geom.RoundRectangle2D; public class Test { private static final RoundRectangle2D.Double RECTANGLE = new RoundRectangle2D.Double(1,6); public static void main(String[] args) { int result = RECTANGLE.hashCode(); long start = System.nanoTime(); for (int i = 0; i < 100_000_000; i++) { result += new RoundRectangle2D.Double(1,6).hashCode(); } System.out.println((System.nanoTime() - start) / 1_000_000); System.out.println(result); } } TL; DR:在循环中使用new关键字比访问静态final字段要快. (注意:删除RECTANGLE上的最终关键字不会更改执行时间) 解决方法
在第一种情况(静态final)中,JVM需要从内存读取对象字段.
在第二种情况下,已知值是常数.此外,由于对象不从循环中逸出,因此省略了分配.其字段被替换为局部变量. 以下JMH基准支持理论: package bench; import org.openjdk.jmh.annotations.*; import java.awt.geom.RoundRectangle2D; @State(Scope.Benchmark) public class StaticRect { private static final RoundRectangle2D.Double RECTANGLE = new RoundRectangle2D.Double(1,6); @Benchmark public long baseline() { return 0; } @Benchmark public long testNew() { return new RoundRectangle2D.Double(1,6).hashCode(); } @Benchmark @Fork(jvmArgs = "-XX:-EliminateAllocations") public long testNewNoEliminate() { return new RoundRectangle2D.Double(1,6).hashCode(); } @Benchmark public int testStatic() { return RECTANGLE.hashCode(); } } 结果: Benchmark Mode Cnt Score Error Units StaticRect.baseline avgt 10 2,840 ± 0,048 ns/op StaticRect.testNew avgt 10 2,831 ± 0,011 ns/op StaticRect.testNewNoEliminate avgt 10 8,566 ± 0,036 ns/op StaticRect.testStatic avgt 10 12,689 ± 0,057 ns/op testNew与返回一个常量一样快,因为对象分配被消除,并且hashCode在JIT编译期间是不变的. 当消除分配优化被禁用时,基准时间显着更高,但是hashCode的算术计算仍然是不变的. 在最后一个基准测试中,即使RECTANGLE被声明为final,它的字段可能在理论上被改变,所以JIT无法消除字段访问. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |