Domanda

Esiste un valore ottimale per il livello di concurrenza oltre il quale le prestazioni di ConcorrentHashmap iniziano a degradare?

Se sì, qual è quel valore e qual è il motivo del degrado delle prestazioni? (Questa domanda si origina nel tentativo di scoprire eventuali limitazioni pratiche che può avere una maestro di concorrente).

È stato utile?

Soluzione

Il Javadoc Offre una guida abbastanza dettagliata:

La concorrenza consentita tra le operazioni di aggiornamento è guidata dall'opzione opzionale concurrencyLevel Argomento del costruttore (impostazione predefinita 16), che viene utilizzato come suggerimento per il dimensionamento interno.

La tabella è partizionata internamente per cercare di consentire il numero indicato di aggiornamenti simultanei senza contesa. Poiché il posizionamento nelle tabelle hash è essenzialmente casuale, la concorrenza effettiva varierà. Idealmente, dovresti scegliere un valore per adattarsi a tutti i thread che mai modificheranno contemporaneamente la tabella. L'uso di un valore significativamente più elevato di quello che serve può sprecare spazio e tempo e un valore significativamente più basso può portare alla contesa del filo. Ma sopravvaluta e sottovaluta all'interno di un ordine di grandezza di solito non hanno un impatto molto evidente. Un valore di uno è appropriato quando è noto che solo un thread si modificherà e tutti gli altri leggono solo.

Riassumere: Il valore ottimale dipende dal numero di aggiornamenti simultanei previsti. Un valore all'interno di un ordine di grandezza dovrebbe funzionare bene. Ci si può aspettare che i valori al di fuori di tale intervallo portino a degrado delle prestazioni.

Altri suggerimenti

Devi farti due domande

  • Quanti CPU ho?
  • Quale percentuale del tempo sarà a utile Il programma accedi alla stessa mappa?

La prima domanda indica il numero massimo di thread che possono accedere alla mappa contemporaneamente. Puoi avere 10000 thread, ma se hai solo 4 CPU, al massimo 4 funzionano contemporaneamente.

La seconda domanda ti dice che la maggior parte di questi thread accederanno alla mappa e faranno qualcosa di utile. Puoi ottimizzare la mappa per fare qualcosa di inutile (ad es. Micro-Benchmark) ma non c'è punto di messa a punto per questo IMHO. Supponi di avere un programma utile che utilizza molto la mappa. Potrebbe essere spendere il 90% delle volte facendo qualcos'altro, ad esempio, accedendo ad altre mappe, costruendo chiavi o valori, facendo qualcosa con i valori che ottiene dalla mappa.

Supponi di passare il 10% del tempo ad accedere a una mappa su una macchina con 4 CPU. Ciò significa che in media accederai alla mappa in 0,4 thread in media. (O un thread circa il 40% delle volte) In questo caso un livello di concorrenza di 1-4 va bene.

In ogni caso, è probabile che il livello di concorrenza sia superiore al numero di CPU che hai non sia necessario, anche per un micro-Benchmark.

A partire da Java 8, ConcurrentHashMapparametro costruttore per per concurrencyLevel è effettivamente inutilizzato, e rimane principalmente per la compatibilità all'indietro. L'implementazione è stata riscritta per utilizzare il primo nodo all'interno di ciascun contenitore hash come blocco per quel contenitore, piuttosto che un numero fisso di segmenti/strisce come nel caso delle versioni precedenti.

In breve, a partire da Java 8, non preoccuparti di impostare il concurrencyLevel Parametro, purché si imposta un valore positivo (diverso da zero, non negativo), secondo il contratto API.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top