2017-05-20 3 views
1

Ich versuche, die Leistung der Erstellung des Objekts einer Klasse mit der Erstellung von String von byte[] zu vergleichen. Hier ist der Maßstab ich dies schrieb:Messung der Leistung der Objekterstellung in Java

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}; 
    } 
} 

wo

private static class TestClass{ 
    private int i; 
    private String s; 

    public TestClass(Integer i, String s) { 
     this.i = i; 
     this.s = s; 
    } 
} 

Auf meinem Rechner habe ich die folgenden Ergebnisse:

Benchmark   Mode Cnt Score Error Units 
MyBenchmark.str avgt 20 47.695 ± 1.869 ns/op 
MyBenchmark.tsts avgt 20 6.999 ± 0.191 ns/op 

Ist es richtig Weg, dies zu tun? Oder habe ich einen Fehler im Benchmark gemacht und etwas verpasst?

+0

Vielleicht hat die JVM 'new TestClass()' (schlechter Name für eine Klasse, btw) so optimiert, dass sie jedes Mal die gleiche Instanz zurückgibt und somit "i" und "str" ​​(mehr schlechte Namen) jeweils nur einmal aufruft. –

+0

Apropos schlechte Namen, das Überladen von 'str' zu zwei völlig verschiedenen Methoden mit dem gleichen Namen ist ein weiteres Beispiel. –

+0

@LewBloch Deshalb frage ich das. Vielleicht hat JVM etwas getan, was ich nicht erwartet habe. Wie immer die gleiche Instanz. –

Antwort

1

Dies liegt daran, JIT kennt die genaue Adresse des Literal String isntance ("asdasfa"). In diesem Fall müssen Sie kein neues Objekt erstellen. Sie können es deutlich sehen, wenn Sie str decompile() -Methode:

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  

Die Methode besteht aus einer Anweisung movabs rax, 0x1bc1f1440, die eine Adresse registrieren rax setzt, das ist, warum es viel mehr schneller ist. Andere Anweisungen sind Hilfsfunktionen.

Für die andere Methode str (Blackhole b) werden Sie viel mehr sehen, einschließlich eines kompilierten Körpers von String-Konstruktor mit einem Standard-Zeichensatz und Decodierung von Byte-Array durch Methodenaufruf.

Verwandte Themen