2013-06-17 10 views
9

Curiosità ed efficienza sono le ragioni di questa domanda. Mi trovo in una situazione in cui sto creando molti nuovi HashSets dopo alcuni cicli eseguiti:Efficienza memoria di cancellazione di un hashset rispetto alla creazione di un nuovo hashset

Il HashSet è attualmente dichiarato come tali al vertice della categoria:

private Set<String> failedTests; 

Poi più tardi nel codice, ho appena creare un nuovo failedTests HashSet ogni volta che sto rieseguire i test:

failedTests = new HashSet<String>(16384); 

lo faccio più e più volte, a seconda delle dimensioni del test. Mi aspetto che il garbage collector gestisca in modo più efficiente i vecchi dati. Ma, io so un'altra opzione sarebbe quella di creare il HashSet inizialmente in principio:

private Set<String> failedTests = new HashSet<String>(16384); 

e quindi deselezionare la HashSet ogni volta attraverso il ciclo.

failedTests.clear(); 

La mia domanda è qual è il modo più efficiente per farlo in termini di spese generali, ecc.? Non so cosa stia facendo la funzione clear(): sta facendo la stessa cosa, inviando i vecchi dati alla garbage collection o sta facendo qualcosa di ancora più efficiente? Inoltre, sto dando all'HashSet un grande cuscinetto di capacità iniziale, ma se un test richiede più di 2^14 elementi, la funzione .clear() sarà nuovamente istanziata da HashSet a 16384?

Per aggiungere, ho trovato il source code to clear() here. Quindi è almeno una operazione O (n) del caso peggiore.

Utilizzando la funzione di cancellazione, ho eseguito un test che ha completato in 565 secondi. Usando il GC per gestirlo, il test è finito in 506 secondi.

Ma non è un punto di riferimento perfetto perché ci sono altri fattori esterni come l'interfaccia con il file system del computer e della rete. Ma un minuto intero sembra davvero piuttosto buono. Qualcuno consiglia uno specifico sistema di profilazione che funzionerà a livello di linea/metodo? (Sto usando Eclipse Indigo)

+0

Hai provato a eseguire il benchmarking? – rob

+0

Hai qualche misura su come * molti * nuovi set stai creando? Hai effettivamente testato il comportamento della tua applicazione? È un caso della domanda * memoria vs prestazioni * che spesso porta a un'ottimizzazione prematura. Come base puoi creare un nuovo 'HashSet', permettere a GC di fare il suo lavoro e fare un po 'di profilazione per vedere i tempi reali prima di preoccuparti. Dopotutto, il metodo 'clear' implica un'iterazione, riferimenti null e permette al GC di fare comunque il suo lavoro. – Gamb

+0

possibile duplicato di [Il modo più veloce per ricreare ArrayList in un ciclo for] (http://stackoverflow.com/questions/11740013/fastest-way-to-recreate-the-arraylist-in-a-for-loop): 'new' è generalmente più veloce di' clear'. – assylias

risposta

6

Non so quale sia la funzione clear() sta facendo all'interno

Si chiama il metodo clear() di HashMap tavolo che sta utilizzando internamente. All'interno HashMap il metodo clear() è definito come segue:

public void clear() { 
    modCount++; 
    Entry[] tab = table; 
    for (int i = 0; i < tab.length; i++) 
     tab[i] = null; 
    size = 0; 
} 

sta facendo la stessa cosa, inviando i vecchi dati per la raccolta dei rifiuti , o sta facendo qualcosa di ancora più efficiente?

tab[i] = null fa notare che sta rendendo i vecchi dati idonei per la garbage collection.

Inoltre, sto dando il HashSet un grande cuscino di capacità iniziale, ma se un test richiede più di 2^14 elementi, sarà il .clear() funzione ripristina un'istanza HashSet a 16384?

No, non lo farà.

quale è il modo più efficiente di farlo in termini di spese generali, ecc.?

Immagino, Java Garbage collector sa come fare il suo lavoro nel modo più efficiente. Quindi lascia che il garbage collector si prenda cura di questo. Quindi, preferirei creare un nuovo Test fallito HashSet ogni volta che è necessario.

+2

Gli oggetti di grandi dimensioni entrano direttamente nello spazio occupato, quindi è più costoso da GC rispetto a quello che è a GC oggetti più piccoli nella generazione da vivaio. Ciononostante, questo costo impallidisce rispetto al costo di iterare attraverso tutti i 16000 elementi dell'array di supporto. –

4

ricreare HashSet è più efficiente.

1) se la capacità HashSet è cresciuto sopra 16384 chiaro non azzerarlo per capacità iniziale

2) nuovo HashSet (16384) crea una nuova voce [16384] array, è un'operazione, è più efficiente di elementi nulling uno alla volta come chiaro

for (int i = 0; i < table.length; i++) 
    tab[i] = null;