Warum / Wenn Sie nicht möchten, dass Java 8 UseStringDeduplication in JVM aktiviert wird?

9

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?

    
Ninetou 07.02.2017, 02:26
quelle

2 Antworten

14

Fälle, in denen die String-Deduplizierung schädlich sein könnte, umfassen:

  • Viele Strings, aber eine sehr geringe Wahrscheinlichkeit für Duplikate: Der Zeitaufwand für die Suche nach Duplikaten und der Zeit- und Platzaufwand für die Entdupping-Hashtabelle würden nicht zurückgezahlt.
  • Eine vernünftige Wahrscheinlichkeit von Duplikaten, aber die meisten Strings sterben innerhalb von ein paar GC-Zyklen 1 : Die Deduplizierung hat viel weniger Vorteile, wenn die De-Dupls bald gecallt werden wie auch immer.

(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.

    
Stephen C 07.02.2017, 02:43
quelle
10

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

erzeugt
  

StringBuilder # 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

    
Eugene 07.02.2017 05:33
quelle