2009-03-30 2 views
10

Sind .NET-Sammlungen mit einer großen Anzahl von Elementen in der LOH gespeichert?.NET-Sammlungen und der Large Object Heap (LOH)

Ich bin neugierig auf List und Wörterbuch speziell. In meinem Code speichere ich eine große Anzahl (40k +) relativ kleiner Objekte (etwa 1k) in temporären Listen und Dictionarys zur Verarbeitung. Erhöht die Anzahl der Artikel in diesen Sammlungen die Wahrscheinlichkeit, dass sie in die LOH aufgenommen werden?

Für Liste, vorausgesetzt, dass Liste als doppelt verknüpfte Liste implementiert ist, dann sollte die Anzahl der Elemente nicht die Größe des tatsächlichen List-Objekts erhöhen, aber ich würde gerne sicher wissen.

Dank

Antwort

13

Objekte werden nur auf dem LOH gespeichert, wenn sie mehr als 85.000 Bytes haben. Eine große Liste (besonders von Strukturen) wird hier oft zugewiesen.

Allerdings sind Dictionarys weniger wahrscheinlich, da sie ein Array von Buckets speichern. Wenn also nicht genug Buckets generiert werden, wird das Array zu> 85000 Bytes, was unwahrscheinlich ist. Eine Liste von 40k-Elementen wird in der LOH gespeichert, auch wenn es Klassen sind (da die Objektreferenzen in jedem Element dazu führen, dass die Liste 160k auf x86, 320k auf x64-Systemen ist). Die einzelnen Elemente befinden sich jedoch auf dem Standard-Heap, also werden sie kompaktiert usw.

Wenn Sie eine doppelt verknüpfte Liste anstelle einer Standardliste verwenden, ist es sehr unwahrscheinlich, dass sie auf der LOH gespeichert wird. Jedes Element der Liste wird klein sein (nur ein einzelner Knoten mit Verweisen auf die nächsten/vorherigen Knoten), so dass kein einzelnes Objekt> 85k Bytes ist.

Einzelheiten zur LOH, this is a great blog entry.

+0

Arrays verdoppelt haben eine untere Grenze, da sie schneller sind, wenn sie auf 8 Byte bounders verbündet, (ebenfalls von List wie es verwendet ein Array) –

+2

Die Implementierung von Dictionary ist als verschmolzenen hashtable (Verkettungs, aber unter Verwendung eines Arrays um die verketteten Buckets zu speichern, um so einige Vorteile der offenen Adressierung zu erhalten, so wie es der Cache-Gebrauch tut), so enthalten sie mit 40k ein internes Array von 40000 * (Keysize + valuesize + 8 [ein Int zum Speichern des Hashcodes und eine, um den nächsten Index in der Kette zu speichern]] und ein internes Array von 40000 * 4 (int-Größe). Das 40000 wird tatsächlich mindestens 43627 sein, vielleicht so viel wie 90523, abhängig von der gewachsenen Geschichte, da es vorberechnete Primzahlen verwendet. Als solches wird es definitiv ... –

+1

... mindestens ein 436270-Byte-Array (wenn Schlüssel und Wert beide Byte-Größe, mehr für jede andere Größe) und mindestens ein 174508-Byte-Array von Indizes sein .Daher würde ein 40k-Element-Wörterbuch ** immer ** einige seiner internen Repräsentationen in der LOH haben (das Wörterbuch selbst ist eher wie 40-80 Bytes und in einer der Generationenhaufen, egal welche Größe). –

4

System.Collections.Generic.List wird intern als ein Array implementiert, nicht eine verkettete Liste. Und ja, wenn die Größe der Sammlung groß ist, wird sie auf großen Objekt-Heapspeicher zugewiesen (beachten Sie, dass die Größe des Arrays wichtig ist, wenn Sie ein kleines Array von großen Referenztypen haben, wird es nicht auf LOH zugewiesen).

4

Liste ist als Array implementiert. Daher wird das Array in LOH gesetzt, das List-Objekt selbst jedoch nicht.

Das Gleiche gilt grundsätzlich auch für Dictionary. Auch hier wird intern ein Array von Buckets verwendet, die im Prinzip die hinzugefügten Schlüssel/Wert-Paare speichern.

0

Wörterbuch hat O (log n) Vektor für den Schlüssel/Wert, so in 40K + Ihre ziemlich sichere Objekte. Wie hier schon gesagt, ist List als Array implementiert, also sind große Listen in der Tat auf dem LOH. Sie können überprüfen, ob Sie object is on the LOH using SOS.