Frage

Warum ist das zweite Stück Code schneller?

Map<Integer, Double> map = new HashMap<Integer, Double>();
for (int i = 0; i < 50000; i++) {
    for (double j = 0.0; j < 10000; j++) {
        map.put(i, j);
    }
}

Map<Integer, Double> map=new HashMap<Integer, Double>();
for (int i = 0; i < 50000; i++) {
    for (double j = 0.0; j < 10000; j++) {            
        map.put(new Integer(i), new Double(j));
    }
}
War es hilfreich?

Lösung

Autoboxing verwendet Integer.valueOf, die intern Caches Integer für kleine Integer-Objekte (standardmäßig -128 bis 127, aber der Maximalwert kann mit der „java.lang.Integer.IntegerCache.high“ Eigenschaft konfiguriert werden - siehe den Quellcode Integer.valueOf), so unterscheidet es sich von new Integer direkt aufrufen. Da Integer.valueOf eine schnelle Überprüfung für die Größe des ganzzahligen Wert hat, bevor new Integer Aufruf, dann ist es ein bisschen schneller Anruf new Integer direkt (obwohl es mehr Speicher verwendet, wenn Sie viele kleine ganze Zahlen haben). Allocation in Java ist sehr schnell, und die Zeit, GC ist proportional zur Anzahl der lebenden kurzlebigen Objekte zu tun (das heißt nicht proportional zu der Menge an Müll), so GC auch sehr schnell ist.

Aber abhängig von der JVM-Version und die Optimierungen aktiviert sind, gibt es die skalare Ersatz-Optimierung, die ein viel größeres Leistungsunterschied in produzieren kann, wenn kurzlebige Objekte Zuteilung (in Ihrem Beispiel, dass die Optimierung nicht durchgeführt werden kann, weil Sie sind die Objekte in einer Karte speichern, aber auch in vielen anderen Situationen ist es sinnvoll).

In den letzten JVM-Versionen gibt es Skalar Ersatz Optimierung ( außer in 1.6.0_18 wo Escape-Analyse ist vorübergehend deaktiviert ), was bedeutet, dass Zuweisungen von kurzlebigen Objekten optimieren entfernt werden. Wenn skalare Ersatz in JVM neu war, jemand gemacht ein Benchmark wo es Code ähnlich wie bei Ihnen. Das Ergebnis war, dass der Code, die Primitiven verwendet wurde, war am schnellsten, der Code mit expliziten new Integer() Anrufen war fast so schnell wie die Primitiven verwendet wird, und den Code, die gebrauchte Autoboxing viel langsamer war. Das lag daran, Autoboxing Anwendungen Integer.valueOf und zumindest damals Skalar Ersatz Optimierung nicht nehmen, dass Sonderfall in Betracht. Ich weiß nicht, ob die Optimierung seitdem verbessert.

Andere Tipps

Autoboxing wird Integer.valueOf und Double.valueOf verwenden. Es gibt einige Overhead, die gleichen Methoden aufrufen (obwohl es wird schließlich bekommen inlined). Auch Integer.valueOf tut einige Kontrollen für Low-Werte zu gepoolt Instanzen zu verwenden, die nicht häufig ein Gewinn in Ihrem Code ist (obwohl es Heap-Größe ein wenig reduzieren könnte). Gepoolt Fällen kann ein Gewinn sein, wo sie Heap-Größe zu reduzieren, GC Zeiten und könnte sogar Gleichheitstest Leistung verbessern ..

Aber im Allgemeinen ist es ein microoptimisation, die Sie sollten in der Regel ignorieren.

Da die Ergebnisse von Microbenchmarks sind unzuverlässig?

Auch Auto-Boxen verwendet Integer.valueOf () und Double.valueOf (), nicht die Konstrukteure.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top