qwe*_*guy 9 java performance static
为什么代码片段比代码片段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);
}
}
Run Code Online (Sandbox Code Playgroud)
代码片段B:
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 += new RoundRectangle2D.Double(1, 2, 3, 4, 5, 6).hashCode();
}
System.out.println((System.nanoTime() - start) / 1_000_000);
System.out.println(result);
}
}
Run Code Online (Sandbox Code Playgroud)
TL; DR:new在循环中使用关键字比访问static final字段更快.
(注意:删除final关键字RECTANGLE不会改变执行时间)
apa*_*gin 16
在第一种情况下(静态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, 2, 3, 4, 5, 6);
@Benchmark
public long baseline() {
return 0;
}
@Benchmark
public long testNew() {
return new RoundRectangle2D.Double(1, 2, 3, 4, 5, 6).hashCode();
}
@Benchmark
@Fork(jvmArgs = "-XX:-EliminateAllocations")
public long testNewNoEliminate() {
return new RoundRectangle2D.Double(1, 2, 3, 4, 5, 6).hashCode();
}
@Benchmark
public int testStatic() {
return RECTANGLE.hashCode();
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
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
Run Code Online (Sandbox Code Playgroud)
testNew与返回常量一样快,因为hashCode在JIT编译期间,对象分配被消除并且是常量折叠的.
当EliminateAllocations禁用优化时,基准时间明显更高,但算术计算hashCode仍然是恒定折叠的.
在最后一个基准测试中,即使RECTANGLE被声明为final,其字段也可能在理论上发生变化,因此JIT无法消除字段访问.
| 归档时间: |
|
| 查看次数: |
726 次 |
| 最近记录: |