2013-06-17 21 views
9

Neugier und Effizienz sind die Gründe für diese Frage. Ich bin in einer Situation, wo ich viele neue HashSets Schaffung bin nach bestimmten Schleifen laufen:Speichereffizienz beim Löschen eines HashSets vs. Erstellen eines neuen HashSets

Die HashSet zur Zeit als solche an der Spitze der Klasse deklariert wird:

private Set<String> failedTests; 

dann später im Code, ich habe gerade erstellen Sie eine neue failedTests HashSet, wann immer ich die Tests erneut ausgeführt wird:

failedTests = new HashSet<String>(16384); 

ich tue dies immer und immer wieder, je nach Größe des Tests. Ich erwarte, dass der Garbage Collector die alten Daten am effizientesten behandelt. Aber ich weiß, eine weitere Option, die HashSet zunächst am Anfang zu schaffen wäre:

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

und deaktivieren Sie dann das HashSet jedes Mal durch die Schlaufe.

failedTests.clear(); 

Meine Frage ist, welches ist der effizienteste Weg, dies in Bezug auf Overhead usw. zu tun? Ich weiß nicht, was die clear() - Funktion im Inneren tut - macht sie dasselbe, sendet die alten Daten an die Garbage Collection oder macht sie etwas noch effizienteres? Außerdem gebe ich dem HashSet ein großes Kissen der Anfangskapazität, aber wenn ein Test mehr als 2^14 Elemente benötigt, wird die .clear() Funktion das HashSet wieder auf 16384 instanziieren?

Um hinzuzufügen, fand ich die source code to clear() here. Es ist also zumindest eine O (n) Operation des Worst-Case.

Mit der Clear-Funktion habe ich einen Testprozess durchgeführt, der in 565 Sekunden endete. Mit dem GC wurde der Test in 506 Sekunden abgeschlossen.

Aber es ist nicht ein perfekter Maßstab, weil es andere externe Faktoren gibt, wie die Schnittstelle mit dem Dateisystem des Computers und des Netzwerks. Aber eine volle Minute fühlt sich tatsächlich ziemlich gut an. Empfiehlt jemand ein bestimmtes Profiling-System, das auf der Linie/Methoden-Ebene funktioniert? (Ich bin mit Eclipse Indigo)

+0

Haben Sie versucht, Benchmarking es? – rob

+0

Haben Sie irgendeine Maßnahme, wie * viele * neue Sets Sie erstellen? Haben Sie das Verhalten Ihrer Anwendung tatsächlich getestet? Es ist ein Fall der * Memory vs Performance * -Frage, die oft zu einer vorzeitigen Optimierung führt. Als Basis können Sie ein neues 'HashSet' erstellen, GC erlauben, seine Arbeit zu tun und ein wenig Profiling zu machen, um die wirklichen Zeiten zu sehen, bevor Sie sich Sorgen machen. Schließlich beinhaltet die "Clear" -Methode eine Iteration, die Referenzen auf Null setzt und dem GC erlaubt, seine Arbeit trotzdem zu machen. – Gamb

+0

mögliches Duplikat von [Schnellste Möglichkeit, die ArrayList in einer for-Schleife neu zu erstellen] (http://stackoverflow.com/questions/11740013/fastest-way-to-recreate-the-arraylist-in-a-for-loop): "neu" ist im Allgemeinen schneller als "klar". – assylias

Antwort

6

Ich weiß nicht, was die klare() Funktion in

tut

Es ist der Aufruf der clear() Methode der HashMap Tabelle, dass es intern verwendet. Innerhalb HashMap wird die clear() Verfahren wie folgt definiert:

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

ist es das gleiche tun, die alten Daten auf den Müll Sammlung zu senden, oder ist es etwas noch effizienter machen?

tab[i] = null weist darauf hin, dass es die alten Daten für die Garbage Collection geeignet macht.

Auch ich bin der HashSet ein großes Kissen von Anfangskapazität zu geben, aber wenn ein Test mehr als 2^14 Elemente erfordert, die .clear() Funktion Wieder instanziiert die HashSet 16384?

Nein, wird es nicht.

Welches ist der effizienteste Weg, dies in Bezug auf Overhead, usw. zu tun?

Ich denke, Java Garbage Collector weiß, wie man seine Arbeit auf effizienteste Weise erledigt. Also lass den Müllsammler dafür sorgen. Also, würde ich lieber jedes Mal ein neues failedTests HashSet erstellen, wenn es benötigt wird.

+2

Große Objekte gehen direkt in den festen Speicherplatz, also ist es teurer, sie zu GC als es ist um kleinere Objekte in der Kinderkrippengeneration zu erfassen. Diese Kosten verblassen jedoch im Vergleich zu den Kosten der Iteration durch alle 16000 Elemente des Hintergrundarrays. –

4

das Erstellen des HashSet ist effizienter.

1), wenn HashSet Kapazität über 16384 clear wuchs wird zurückgesetzt es nicht zu Anfangskapazität

2) Neuer HashSet (16384) erstellt ein neuer Eintrag [16384] -Array, es ist eine Operation, es ist effizienter als nulling Elemente eins nach eins wie klar macht

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