我正在尝试将创建某个类的对象的效果与来自String
的{{1}}的创建进行比较。这是我为此写的基准:
byte[]
其中
public class MyBenchmark {
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void tsts(Blackhole b) {
b.consume(new TestClass(i(), str()));
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void str(Blackhole b) {
b.consume(new String(b()));
}
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
public String str(){
return "asdasfa";
}
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
public int i(){
return 23;
}
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
public byte[] b(){
return new byte[]{49, 66, 43, 65, 78, 123, 96, 54};
}
}
在我的机器上,我得到了以下结果:
private static class TestClass{
private int i;
private String s;
public TestClass(Integer i, String s) {
this.i = i;
this.s = s;
}
}
这样做是否正确?或者我在基准测试中犯了一些错误而遗漏了什么?
答案 0 :(得分:2)
这是因为JIT知道文字String isntance(“asdasfa”)的确切地址。因此,在这种情况下,不需要创建新对象。如果你反编译str()方法,你可以清楚地看到它:
0x000000010dd1a2b0: sub rsp,0x18
0x000000010dd1a2b7: mov QWORD PTR [rsp+0x10],rbp ;
0x000000010dd1a2bc: movabs rax,0x1bc1f1440 ; {oop("asdasfa")}
0x000000010dd1a2c6: add rsp,0x10
0x000000010dd1a2ca: pop rbp
0x000000010dd1a2cb: test DWORD PTR [rip+0xfffffffffe642d2f],eax # 0x000000010c35d000;
0x000000010dd1a2d1: ret
该方法由一条指令movabs rax,0x1bc1f1440组成,它将一个地址放入rax寄存器,这就是为什么它的速度要快得多。其他说明是辅助的。
对于另一个方法str(Blackhole b),您将看到更多内容,包括String构造函数的编译体,获取默认字符集并通过方法调用解码字节数组。