2009-09-15 9 views
9

In Java, wenn ich eine Hashtable<K, V> erstellen und N Elemente darin einfügen, wie viel Speicher wird es belegen? Wenn es implementierungsabhängig ist, was wäre eine gute "Annahme"?Wie viel Speicher verwendet eine Hashtable?

+0

Wahrscheinlich wird es von der Größe Ihrer Schlüssel- und Wertobjekte dominiert (mit Ausnahme von kleinen Karten). –

+0

Ich habe eine genaue Berechnung hinzugefügt, obwohl diese mit der VM variieren kann. Das stimmt nicht immer. Bei sehr kleinen Schlüsseln und Werten (z. B. bei Wrapper-Objekten für Primitive) kann die Größe der Entry-Objekte die Größe der Hashmappe/Hashtabelle dominieren (intern sind sie gleich). Dies kann auch passieren, wenn mehrere Werte Referenzen auf dieselbe Objektinstanz sind. Wenn Sie viele primitive Objekte als Schlüssel oder Werte verwenden, sehen Sie sich die Trove-Bibliothek an. Dies ist schneller und effizienter. – BobMcGee

Antwort

12

Bearbeiten; Oh mein Gott, ich bin ein Idiot, ich gab Informationen für HashMap, nicht HashTable. Nach der Überprüfung sind die Implementierungen jedoch für Speicherzwecke identisch.

Dies ist abhängig von der internen Speicherkonfiguration Ihrer VM (Packen von Elementen, 32-Bit- oder 64-Bit-Zeigern und Wortausrichtung/-größe) und wird nicht von Java angegeben.

Grundlegende Informationen zur Schätzung der Speicherbelegung finden Sie unter here.

Man kann es so wie schätzen:

  • Auf 32-Bit-VMs, ein Zeiger 4 Bytes ist, auf 64-Bit-VMs ist es 8 Bytes.
  • Objekt-Overhead ist 8 Byte Speicher (für ein leeres Objekt, das nichts enthält)
  • Objekte werden auf eine Größe aufgefüllt, die ein Vielfaches von 8 Byte (ugh) ist.
  • Es gibt einen kleinen, konstanten Overhead für jede Hashmap: ein Float, 3 Ints, plus Objekt Overhead.
  • Es gibt eine Reihe von Steckplätzen, von denen einige Einträge haben, von denen einige für neue reserviert sind. Das Verhältnis von gefüllten Slots zu gesamten Slots ist KEINER als der angegebene Auslastungsfaktor im Konstruktor.
  • Das Slot-Array benötigt einen Objekt-Overhead plus ein int für die Größe sowie einen Zeiger für jeden Slot, um das gespeicherte Objekt anzuzeigen.
  • Die Anzahl der Steckplätze ist im Allgemeinen 1,3- bis 2-mal höher als die Anzahl der gespeicherten Zuordnungen bei einem Standardauslastungsfaktor von 0,75, kann jedoch je nach Hash-Kollision geringer sein.
  • Jedes gespeicherte Mapping erfordert ein Eintragsobjekt. Dies erfordert einen Objektoverhead, 3 Zeiger sowie die gespeicherten Schlüssel- und Wertobjekte sowie eine Ganzzahl.

So setzen sie zusammen (für 32/64 Bit Sun HotSpot JVM): HashMap benötigt 24 Bytes (selbst, primtive Felder) + 12 Bytes (slot-Array konstant) + 4 oder 8 Byte pro Schlitz + 24/40 Bytes pro Eintrag + Schlüsselobjektgröße + Wert Objektgröße + padding jedes Objekt Vielfaches von 8 Bytes

OR, etwa (in den meisten Standardeinstellungen nicht garantiert um genau zu sein):

  • Auf 32-Bit-JVM: 36 Bytes + 32 Bytes/Mapping + Tasten &
  • Auf 64-Bit-JVM-Werte: 36 Bytes + 56 Bytes/Mapping + Tasten &

Notenwerte: Diese benötigt mehr Überprüfung, benötigt möglicherweise 12 Bytes für Objekt-Overhead auf 64-Bit-VM. Ich bin mir nicht sicher über Nullen - Zeiger für Nullen können irgendwie komprimiert werden.

4

Es ist schwer zu schätzen. Ich würde zuerst lesen: http://www.codeinstructions.com/2008/12/java-objects-memory-structure.html

einfach die sunjdk Tools verwenden, um die Größe von K, V, um herauszufinden, und

jmap -histo [pid]

num #instances #bytes Klassenname

1: 126170 19.671.768 MyKClass

2: 126170 14.392.544 MyVClass

3: 1 200000 MyHashtable

Sie können auch HashMap anstelle von Hashtable verwenden, wenn Sie keine Synchronisation benötigen.

Verwandte Themen