Java 8 führte die Zeichenketten-Deduplizierung ein, die durch den Start von JVM mit der Option -XX:+UseStringDeduplication
aktiviert werden kann, um Speicherplatz zu sparen, indem ähnliche String
-Objekte referenziert werden, anstatt Duplikate beizubehalten. Natürlich ist die Effektivität von Programm zu Programm unterschiedlich, abhängig von der Verwendung von Strings
, aber ich denke, dass es im Allgemeinen als vorteilhaft für die meisten Anwendungen (wenn nicht alle) betrachtet werden kann, die mich über wenige Dinge wundern:
Warum ist es nicht standardmäßig aktiviert? Liegt es an den mit der Deduplizierung verbundenen Kosten oder daran, dass G1GC noch immer als neu betrachtet wird?
Gibt es (oder gab es) Randfälle, in denen Sie keine Deduplizierung verwenden möchten?
Fälle, in denen die String-Deduplizierung schädlich sein könnte, umfassen:
(Im zweiten Fall geht es nicht um Zeichenketten, die den ersten GC-Zyklus nicht überleben. Es wäre für den GC sinnlos, zu versuchen Deduplizierungen von Zeichenketten durchzuführen, von denen er weiß, dass sie unbrauchbar sind .)
Wir können nur darüber spekulieren, warum das Java-Team standardmäßig keine Deduplizierung vorgenommen hat, aber sie sind in einer viel besseren Position, um rationale (dh evidenzbasierte) Entscheidungen darüber zu treffen, dass Sie und ich ist, dass sie Zugang zu vielen großen realen Anwendungen haben, um die Auswirkungen von Optimierungen zu vergleichen und auszuprobieren. Sie haben möglicherweise auch enge Kontakte zu einer Reihe von Partner- oder Kundenorganisationen mit ähnlich großen Code-Grundlagen und Bedenken hinsichtlich der Effizienz ... die sie um Informationen bitten könnten, welche Optimierungen wirklich funktionieren.
1 - Dies hängt vom Wert von StringDeduplicationAgeThreshold
ab
JVM-Einstellung. Dies ist standardmäßig 3, was bedeutet, dass (ungefähr) eine Zeichenkette 3 kleinere Sammlungen oder eine größere Sammlung überstehen muss, die für das Deduping berücksichtigt werden sollen. Wenn jedoch ein String enttippt wird und kurz danach nicht mehr erreichbar ist, werden die Deduping-Overheads für diesen String nicht zurückgezahlt.
Wenn Sie fragen, wann Sie eine Deduplizierung in Betracht ziehen sollten, wäre mein Ratschlag, es zu versuchen und zu sehen, ob es auf einer Anwendungsbasis hilft . Aber Sie müssen ein Benchmarking auf Anwendungsebene durchführen (was Aufwand kostet!), Um sicher zu sein, dass das Deduping von Vorteil ist ...
Eine sorgfältige Lektüre von JEP 192 würde Ihnen auch helfen, die Probleme zu verstehen und zu beurteilen, wie sie sich anwenden lassen für Ihre Java-Anwendung.
Ich verstehe absolut, dass dies die Frage nicht beantwortet, wollte nur erwähnen, dass jdk-9 eine weitere Optimierung einführt, die standardmäßig aufgerufen wird:
-XX: + CompactStrings
Dabei belegen Latin1 Zeichen ein einzelnes Byte statt zwei (über ein Zeichen). Aufgrund dieser Änderung haben sich viele interne Methoden von String geändert - sie verhalten sich für den Benutzer gleich, aber intern sind sie in vielen Fällen schneller.
Auch im Fall von Strings zum Verketten von zwei Strings zusammen über das Pluszeichen wird der javac einen anderen Bytecode erzeugen.
Es gibt keinen Bytecode-Befehl, der zwei Strings miteinander verkettet, so dass der Javac ein
erzeugtStringBuilder # append
im Back-End. Bis jdk-9.
Jetzt delegiert der Bytecode an
StringConcatFactory # makeConcatWithConstants
oder
StringConcatFactory # makeConcat
über die aufgerufene dynamische Bytecode-Anweisung:
%Vor%Wie die beiden Strings verkettet werden, ist jetzt eine Laufzeitentscheidung. es könnte immer noch ein StringBuilder sein oder es könnte eine Verkettung von Byte-Arrays, usw. sein. Alles, was Sie wissen, kann sich ändern und Sie werden die schnellstmögliche Lösung bekommen.
BEARBEITEN
Ich habe gerade debuggt und gesehen, dass es ziemlich viele Strategien gibt, wie man diese Strings anhängt:
%Vor%Der Standardwert ist:
MH_INLINE_SIZED_EXACT
Tags und Links java optimization java-8 performance