测量Java中对象创建的性能

时间:2017-05-20 14:54:10

标签: java performance jmh

我正在尝试将创建某个类的对象的效果与来自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;
    }
}

这样做是否正确?或者我在基准测试中犯了一些错误而遗漏了什么?

1 个答案:

答案 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构造函数的编译体,获取默认字符集并通过方法调用解码字节数组。