Warum wird eine Out of Memory-Ausnahme ausgelöst, wenn Speicher verfügbar ist?

9

Ich habe eine ziemlich einfache C # -Anwendung, die eine große Hashtabelle erstellt hat. Die Schlüssel dieser Hashtabelle sind Strings und die Werte sind Ints.

Das Programm läuft gut, bis etwa 10,3 Millionen Elemente zur Hashtabelle hinzugefügt wurden, wenn ein Fehler wegen zu wenig Speicher in der Zeile erscheint, die der hasbtable ein Element hinzufügt.

Laut dem Task-Manager verwendet mein Programm nur 797 MB Speicher, und es sind immer noch mehr als 2 GB verfügbar. Es ist eine 32-Bit-Maschine, also weiß ich, dass nur ein Gesamtwert von 2 GB von einem Prozess verwendet werden kann, aber das lässt immer noch etwa 1,2 GB übrig, in die die Hashtabelle expandieren könnte.

Warum wird ein Fehler wegen zu wenig Speicher ausgegeben?

    
Paul 27.06.2010, 14:41
quelle

7 Antworten

11

Theoretisch erhalten Sie 2 GB für den Prozess, aber die Realität ist, dass es 2 GB zusammenhängender Speicher ist. Wenn also der Speicher Ihres Prozesses fragmentiert ist, erhalten Sie weniger als das.

Außerdem vermute ich, dass die Hash-Tabelle wie die meisten Datenstrukturen standardmäßig verdoppelt wird, wenn sie wachsen muss, was zu einem großen Wachstum führt, wenn der Tipppunkt hinzugefügt wird.

Wenn Sie die Größe kennen, die im Voraus benötigt wird (oder eine angemessene Überschätzung haben), kann es hilfreich sein, die Kapazität im Konstruktor anzugeben.

Alternativ, wenn es nicht entscheidend ist, dass es im Speicher ist, kann eine Art von Datenbanklösung besser sein und Ihnen mehr Flexibilität geben, wenn es den Punkt erreicht, dass es nicht in den Speicher passen kann.

    
Davy8 27.06.2010, 14:47
quelle
4

Wahrscheinlich liegt das an der Speicherfragmentierung: Sie haben immer noch freien Speicher, aber nicht zusammenhängend. Der Speicher ist in Seiten unterteilt, normalerweise 4 KB groß. Wenn Sie also 4 MB zuweisen, benötigen Sie 1024 zusammenhängende Speicherseiten in Ihrem Prozessadressraum (sie sind nicht < em> physisch zusammenhängend, da der Speicher pro Prozess virtualisiert wird.

Allerdings muss der Speicher für die Hashtabelle nicht zusammenhängend sein (es sei denn, es ist sehr schlecht implementiert), also ist es vielleicht eine Grenze des Speichermanagers ...

    
Wizard79 27.06.2010 14:45
quelle
3

Verwenden Sie Process Explorer (www.sysinternals.com) und sehen Sie sich den virtuellen Adressraum Ihres Prozesses an. Im Gegensatz zu "Private Bytes" (dh der Speichermenge, die vom Prozess belegt wird) zeigt der virtuelle Adressraum die höchste verwendete Speicheradresse an. Wenn die Fragmentierung hoch ist, ist sie viel höher als die "Private Bytes".

Wenn Ihre Anwendung wirklich so viel Speicher benötigt:

  • Ziehen Sie in Betracht, zu 64-Bit
  • zu gehen
  • Aktivieren Sie das Flag / LARGEADDRESSAWARE, das Ihrem 32-Bit-Prozess 4 GB RAM unter einem 64-Bit-Betriebssystem und 3 GB gibt, wenn ein 32-Bit-Windows mit dem Flag / 3GB gestartet wird.
Patrick 27.06.2010 14:53
quelle
1

Sie schauen einfach auf die falsche Spalte. Sehen Sie sich die Spalte "Commit Size" an, diese sollte ungefähr 2 GB groß sein.

Ссылка

    
Lucero 27.06.2010 14:54
quelle
1

Das Programm, das Sie ausführen, hat begrenzte Ressourcen dank des Visual Studio-Debuggers, der versucht, alles zu verfolgen, was Sie in Ihrer Anwendung tun (Haltepunkte, Referenzen, Stapel usw.).

Darüber hinaus haben Sie möglicherweise mehr Dinge, die noch nicht intakt sind, als Sie denken. Der Garbage Collector ist abgestuft und sammelt langsam große Objekte sehr .

%Vor%

HINWEIS: Die Zahlen sind aus dem Speicher, also nehmen Sie es mit einem Körnchen Salz.

    
Tim 27.06.2010 14:55
quelle
0

Sie sollten etwas wie hibrid zwischen dem Array und der verknüpften Liste verwenden. Da die verknüpfte Liste pro Element mehr Speicher benötigt als das Array, benötigt das Array jedoch fortlaufenden Speicherplatz.

    
TcKs 27.06.2010 14:52
quelle
0

Ich habe meine Version dieses Problems gelöst, indem ich das Kontrollkästchen "32-Bit bevorzugen" auf der Seite Projekteigenschaften der exe auf der Registerkarte Erstellen

deaktiviert habe     
Sean 28.03.2013 19:33
quelle

Tags und Links