2015-09-29 20 views
13

Sto leggendo sulla funzionalità di Java 8 update 20 per deduplicazione String (more info) ma non sono sicuro se ciò rende sostanzialmente obsoleto lo String.intern().Deduplicazione Java 8 String vs. String.intern()

So che questa funzione JVM richiede il garbage collector G1, che potrebbe non essere un'opzione per molti, ma supponendo che uno stia utilizzando G1GC, c'è qualche differenza/vantaggio/svantaggio della deduplicazione automatica eseguita da JVM vs manualmente dovendo intern le tue stringhe (una ovvia è il vantaggio di non dover inquinare il tuo codice con le chiamate a intern())?

Ciò è particolarmente interessante se si considera che Oracle potrebbe rendere G1GC il GC di default in java 9

+3

[Video consigliato] (https://www.youtube.com/watch?v=YgGAUGC9ksk) - ma in ogni caso, la conclusione è sempre la stessa: tu. Dovrebbero. Non. Cura. – fge

+0

scusa, non dovrebbe importarmi di cosa? su quale usare (cioè sono equivalnet) o sulla nuova funzionalità (il che significa che non è così utile) ?? – Hilikus

+2

Significato: basta usare la classe 'String' senza pensarci due volte. – fge

risposta

6

Con questa funzione, se si dispone di 1000 oggetti String distinte, tutte con lo stesso contenuto "abc", JVM potrebbe fare condivide la stessa char[] internamente. Tuttavia, hai ancora 1000 distinti oggetti String.

Con intern(), si avrà un solo oggetto String. Quindi, se il risparmio di memoria è la tua preoccupazione, sarebbe meglio. Risparmierà spazio e tempo in GC.

Tuttavia, le prestazioni di intern() non sono eccezionali, l'ultima volta che ho ascoltato. Potresti stare meglio avendo la tua cache di stringhe, anche usando uno ConcurrentHashMap ... ma devi assicurarti che sia necessario un benchmark.

+0

sei a conoscenza di altre differenze? – Hilikus

+3

In realtà, le prestazioni con String.intern sono paragonabili al pooling di stringhe manuale. Mikhail Vorontsov ha fatto alcuni benchmark delle prestazioni e ha dimostrato che con il parametro StringTableSize impostato su un valore sufficientemente alto, che le prestazioni erano paragonabili al pooling manuale delle stringhe. [http://java-performance.info/string-intern-in-java-6-7-8/](http://java-performance.info/string-intern-in-java-6-7-8 /) –

2

voglio introdurre un altro fattore di decisione per quanto riguarda il pubblico mirato:

  • Per un integratore di sistema con un sistema composto da molte diverse biblioteche/quadri, con bassa capacità di influenzare quelle librerie di sviluppo interno, StringDeDuplication potrebbe essere un rapido vincitore se la memoria è un problema. Influirà su tutte le stringhe nella JVM, ma G1 utilizzerà solo il tempo libero per farlo. È possibile modificare anche DeDuplication utilizzando un altro parametro (StringDeduplicationAgeThreshold)
  • Per uno sviluppatore che profila il proprio codice, String.intern potrebbe essere più interessante. Una revisione attenta del modello di dominio è necessaria per decidere se chiamare intern, e quando. Come regola empirica, è possibile utilizzare stag se sapete che la stringa conterrà un insieme limitato di valori, come un tipo di set enumerato (ad esempio nome del paese, mese, giorno della settimana ...).
4

Come riferimenti di commento, vedere: http://java-performance.info/string-intern-in-java-6-7-8/. È un riferimento molto perspicace e ho imparato molto, tuttavia non sono sicuro che le sue conclusioni siano necessariamente "taglia unica". Ogni aspetto dipende dalle esigenze della propria applicazione: si consiglia di effettuare misurazioni di dati di input realistici!

Il principale fattore probabilmente dipende da ciò che siete in controllo su:

  • Hai il pieno controllo sulla scelta di GC? Ad esempio, in un'applicazione GUI, è ancora necessario creare un caso valido per l'utilizzo del Serial GC. (molto più basso ingombro di memoria totale per il processo - si pensi 400 MB vs ~ 1 GB per un'app moderatamente complessa, e si tratti di memoria di rilascio molto più voluta, ad esempio dopo un picco transitorio nell'utilizzo). Quindi potresti sceglierlo o dare la possibilità ai tuoi utenti. (Se il mucchio rimane piccolo, le pause non dovrebbero essere un grosso problema).

  • Hai il pieno controllo del codice?L'opzione G1GC è ottima per le librerie di terze parti (e le applicazioni!) Che non puoi modificare.

La seconda considerazione (come da @ risposta di Zhongyu) è che String.intern può de-duplicazione del String stessi oggetti, mentre G1GC necessariamente non può che de-duplicare il loro privato char[] campo.

Una terza considerazione potrebbe essere l'utilizzo della CPU, ad esempio se l'impatto sulla durata della batteria del laptop potrebbe essere di interesse per gli utenti. G1GC eseguirà un thread aggiuntivo dedicato alla deduplicazione dell'heap. Ad esempio, ho giocato con questo per eseguire Eclipse e ho scoperto che causava un periodo iniziale di maggiore attività della CPU dopo l'avvio (penso 1 - 2 minuti) ma si stabiliva su un heap più piccolo "in uso" e non ovvio (solo occhio- balling the task manager) CPU overhead o rallentamento in seguito. Quindi immagino che una certa percentuale di core della CPU sarà occupata dai periodi di de-duplicazione (durante? Dopo?) Di alta memoria. (Naturalmente ci può essere un sovraccarico paragonabile se si chiama String.Intern ovunque, che gestisce anche in serie, ma poi ...)

Probabilmente non c'è bisogno stringa di de-duplicazione in tutto il mondo. Ci sono probabilmente solo alcune aree del codice che:

  • davvero impatto utilizzo di heap-lungo termine, e
  • creare una elevata percentuale di stringhe duplicate

Utilizzando String.intern selettivo, altre parti del codice (che può creare stringhe temporanee o semi-temporanee) non pagano il prezzo.

E, infine, una presa rapida per l'utilità Guava: Interner, che:

Fornisce comportamento equivale a String.intern() per altri tipi immutabili

È inoltre possibile utilizzare tale per archi. La memoria probabilmente è (e dovrebbe essere) la vostra preoccupazione in termini di prestazioni, quindi probabilmente non si applica spesso: tuttavia, quando è necessario ridurre ogni goccia di velocità da alcune aree hot-spot, la mia esperienza è quella di riferimento debole basato su Java Le soluzioni HashMap vengono eseguite leggermente, ma in modo coerente più veloce dell'implementazione C++ JVM di String.intern(), anche dopo aver ottimizzato le opzioni di jvm. (E bonus: non è necessario sintonizzare le opzioni JVM per adattarsi a input diversi.)