2016-10-31 1 views
2

Was sind die Speicherbeschränkungen eines Hashset<string> in C#?Was sind die Speichergrenzen eines HashSet?

Ich habe gesehen, dass .NET ein Speicherlimit von 2 GB pro Objekt hat? Sind diese Informationen immer noch korrekt? Gilt es für Hashsets?

Ich arbeite gerade an einer Anwendung, die mit einem großen hashset funktioniert und ich habe gesehen, sobald ich die DLLs für 64-Bit-Umgebung baue, bekomme ich OutOfMemory nur, wenn mein 8GB RAM-Laptop seine Speichergrenzen erreicht.

Wenn ich von 16GB RAM hätte würde das Objekt erhöhen, bis es die Hardware-Einschränkungen erreicht?

+0

Duplizieren? http: // Stapelüberlauf.com/a/1088044/993547 –

+1

Die Beschränkung von 2 GB gilt für einzelne Objekte und wirkt sich auf die maximale Größe von Arrays als Beispiel aus. Wenn jedoch die in einem Hash-Set gespeicherten 'T's Klassen sind, dann wird nur eine 32- oder 64-Bit-Referenz im Hash-Set gespeichert, die tatsächliche Objektinstanz und ihre Größe sind im Zusammenhang mit der Hashset. OutOfMemory im Allgemeinen bedeutet, dass .NET wirklich nicht genügend Arbeitsspeicher zur Verfügung hat, es sollte niemals bedeuten, dass irgendein beliebiges Objekt entschieden hat, dass dies so hoch wie möglich ist. –

+0

Das Limit von 2 GB ist nicht mehr so ​​einfach; Es gibt eine 'gcAllowVeryLargeObjects'-Option - aber der' int.MaxValue'-Grenzwert gilt auch dann, wenn das aktiviert ist. im Falle von 'T' =' string' könnten Sie vielleicht ein bisschen größer werden, wenn ** ** HashSet 'durch große Arrays begrenzt ist! nicht trivial –

Antwort

2

Es gibt ein Limit von 2 GB pro Objekt, aber denken Sie daran, dass ein Referenztyp nur die Zeigergröße (8 Bytes für x64) verwendet, wenn es ein Feld in einer Klasse ist.

Array Speichergrößen werden wie folgt berechnet (fixed-Overhead zu ignorieren):

Für Arrays von Strukturtypen:

  • Array Speichergrße = #elements im Array * Größe jedes Elements

Für Arrays von Referenztypen:

  • Array Speicher size = # Elemente im Array * Referenzgröße (4 Bytes für x8x, 8 Bytes für x64)

Ein HashSet könnte also Objekte referenzieren, die mehr als die 2GB Grenze umfassen. Wenn Sie die Größe für jedes Feld in der Klasse addieren - 64 Bit für Referenztypen und die volle Größe für Strukturtypen - muss es weniger als 2 GB betragen.

Sie könnten eine Klasse haben, die zum Beispiel 16x1GB Arrays von Bytes enthält.

Beachten Sie auch, dass es möglich ist, eine Anwendung so zu konfigurieren, dass Arrays mit einer Größe von mehr als 2 GB zulässig sind. Die maximale Anzahl von Elementen in einem eindimensionalen Array kann 2G (2 * 1024 * 1024 * 1024) jedoch nicht überschreiten.

Ich vermute, dass die Objekte, die Sie in der HashSet speichern, Referenztypen sind, so dass es nur 64 Bits für jede im internen HashSet-Array verwendet, während die volle Größe jedes Ihrer Objekte viel größer als 64 Bit ist - Das ergibt eine Gesamtgröße von mehr als 2 GB.

am referencesource für HashSet Blick zeigt, dass die folgenden Felder verwendet:

private int[] m_buckets; 
private Slot[] m_slots; 

Wo Slot wie so definiert:

internal struct Slot { 
    internal int hashCode;  // Lower 31 bits of hash code, -1 if unused 
    internal T value; 
    internal int next;   // Index of next entry, -1 if last 
} 

Es ist wie jeder nimmt Slot Struktur aussieht 16 Bytes auf x64 Wenn T ein Referenztyp ist, bedeutet dies, dass HashSet OutOfMemory auslöst, wenn die Anzahl der verwendeten Slots 2GB/16 = 128M Elemente

0 überschreitet

(Wenn T eine Struktur ist, wird der Speicher je nach Größe viel schneller verbraucht.)

+0

@LaRage Da Sie Strings speichern, können Sie ~ 128 * 1024 * 1024 speichern, bevor Sie OutOfMemory erhalten. Wenn Sie ein großes Objekt aktivieren, denke ich, dass Sie ~ 2 * 1024 * 1024 * 1024 davon speichern können, bevor Sie eine Ausnahme erhalten, weil Sie zu viele Elemente haben. Aber Sie müssten das testen, um definitiv zu sein!Ich weiß es nicht genau. –

Verwandte Themen