'System.OutOfMemoryException " wurde ausgelöst, wenn es ist immer noch genug Speicher frei
Dies ist mein code:
int size = 100000000;
double sizeInMegabytes = (size * 8.0) / 1024.0 / 1024.0; //762 mb
double[] randomNumbers = new double[size];
Ausnahme:
Ausnahme des Typs " System.OutOfMemoryException " wurde ausgelöst.
Ich habe 4 GB Speicher auf dieser Maschine 2,5 GB frei wenn ich dieses ausführen, es ist eindeutig genug Speicherplatz auf dem PC zu handhaben, die 762mb von 100000000 Zufallszahlen. Ich brauche, um zu speichern, wie viele Zufallszahlen wie möglich, da Verfügbarer Speicher. Wenn ich in die Produktion gehen wird es 12 GB auf die box und ich wollen es nutzen.
Funktioniert die CLR zwingst mich zu einer Standard-max-Speicher, mit zu beginnen? und wie fordere ich mehr?
Update
Dachte ich, brechen diese in kleinere Abschnitte zu unterteilen und nach und nach hinzufügen zu meinen Anforderungen an den Arbeitsspeicher würde helfen, wenn das Problem ist aufgrund Fragmentierung des Speichersaber es funktioniert nicht ich kann nicht vorbei an insgesamt ArrayList Größe von 256 MB, unabhängig davon, was ich tun tweaking blockSize.
private static IRandomGenerator rnd = new MersenneTwister();
private static IDistribution dist = new DiscreteNormalDistribution(1048576);
private static List<double> ndRandomNumbers = new List<double>();
private static void AddNDRandomNumbers(int numberOfRandomNumbers) {
for (int i = 0; i < numberOfRandomNumbers; i++) {
ndRandomNumbers.Add(dist.ICDF(rnd.nextUniform()));
}
}
Aus meiner main-Methode:
int blockSize = 1000000;
while (true) {
try
{
AddNDRandomNumbers(blockSize);
}
catch (System.OutOfMemoryException ex)
{
break;
}
}
double arrayTotalSizeInMegabytes = (ndRandomNumbers.Count * 8.0) / 1024.0 / 1024.0;
InformationsquelleAutor der Frage m3ntat | 2009-07-20
Du musst angemeldet sein, um einen Kommentar abzugeben.
Möchten Sie vielleicht, dies zu Lesen: ""Out Of Memory" bezieht sich Nicht auf den Physischen Speicher" von Eric Lippert.
In kurz und sehr vereinfacht, "Out of memory" bedeutet nicht wirklich, dass der verfügbare Arbeitsspeicher ist zu klein. Der häufigste Grund ist, dass in der aktuellen Adressraum, es gibt keinen zusammenhängenden Teil des Speichers, der groß genug ist, um zu dienen die gesuchte Zuordnung. Wenn Sie 100 Blöcke, je 4 MB groß, dass ist nicht zu helfen, wenn Sie brauchen, einer 5 MB block.
Wichtigsten Punkte:
InformationsquelleAutor der Antwort Fredrik Mörk
Sie nicht über einen kontinuierlichen Speicherblock, um zu reservieren 762MB, Ihr Speicher ist fragmentiert und die Zuweisung nicht finden können, ein genügend großes Loch zum reservieren des benötigten Speichers.
InformationsquelleAutor der Antwort Shay Erlichmen
Überprüfen Sie, dass der Aufbau einer 64-bit-Prozess, und nicht eine 32-bit-Version, die die Standard-Zusammenstellung-Modus von Visual Studio. Um dies zu tun, klicken Sie rechts auf Ihr Projekt, Eigenschaften -> Erstellen -> Plattform Ziel : x64. Wie alle 32-bit-Prozess, Visual Studio kompilierte Anwendungen, die in 32-bit virtueller Arbeitsspeicher-limit von 2GB.
64-bit-Prozesse haben diese Einschränkung nicht, da Sie die Verwendung der 64-bit-Zeiger, also Ihre theoretische maximale Adressraum (von der Größe Ihrer virtuellen Speicher) ist 16 Exabyte (2^64). In der Realität, Windows x64 begrenzt den virtuellen Speicher der Prozesse, die zu 8 TB. Die Lösung für das memory limit problem ist, dann kompilieren in 64-bit.
Jedoch, Objekt-Größe in Visual Studio ist immer noch auf 2 GB beschränkt, standardmäßig. Sie werden in der Lage sein, um erstellen Sie mehrere arrays, deren kombinierte Größe wird größer sein als 2 GB, aber Sie können nicht standardmäßig erstellen von arrays, die größer als 2 GB. Hoffentlich, wenn Sie immer noch wollen, zum erstellen von arrays, die größer als 2 GB ist, können Sie es durch hinzufügen des folgenden code-app.config-Datei:
InformationsquelleAutor der Antwort Shift Technology
Wie Sie wahrscheinlich herausgefunden, das Problem ist, dass Sie versuchen, zu reservieren, einem großen zusammenhängenden block von Speicher, die nicht durch Arbeit, um die Fragmentierung des Speichers. Wenn ich brauchte, um zu tun, was Sie tun, würde ich Folgendes tun:
Dann, zu einem bestimmten index, den Sie verwenden würde
randomNumbers[i /sizeB][i % sizeB]
.Weitere option, wenn Sie immer auf die Werte, um die Verwendung von der überladene Konstruktor , geben Sie die Samen. Auf diese Weise erhalten Sie eine halb-zufällige Zahl (wie die
DateTime.Nun.Zecken
) in einer Variablen gespeichert, dann, Wann immer Sie gehen Sie durch die Liste, erstellen Sie eine neue Random Instanz unter Verwendung der original-Saatgut:Es ist wichtig zu beachten, dass, während die blog verlinkt in Fredrik Mörk Antwort zeigt an, dass das Problem in der Regel durch einen Mangel an Adressraum es nicht eine Reihe anderer Fragen, wie die 2GB CLR-Objekt Größenbeschränkung (erwähnt in einem Kommentar von ShuggyCoUk auf dem gleichen blog), beschönigt der Fragmentierung des Speichers und nicht zu schweigen von den Auswirkungen, die die Größe der Auslagerungsdatei (und wie es behoben werden kann mit der Nutzung der
CreateFileMapping
- Funktion).Die 2GB Beschränkung bedeutet, dass
randomNumbers
muss kleiner sein als 2GB. Da arrays Klassen und ein gewisser Aufwand, Sie selbst dies bedeutet, dass ein array vondouble
müssen kleiner sein als 2^31. Ich bin nicht sicher, wie viel kleiner ist dann 2^31 die Länge müsste, aber Overhead ein .NETTO-array? zeigt 12 - 16 bytes.Fragmentierung des Speichers ist sehr ähnlich zu Festplatte Fragmentierung. Haben Sie vielleicht 2 GB Adressraum, aber wie Sie erstellen und zerstören von Objekten gibt es Lücken zwischen den Werten. Wenn diese Lücken sind zu klein für Ihre großen Objekt, und der zusätzliche Raum kann nicht angefordert werden, dann erhalten Sie die
System.OutOfMemoryException
. Zum Beispiel, wenn Sie 2 Millionen, 1024-byte-Objekte, dann sind Sie mit 1.9 GB. Wenn Sie das löschen jedes Objekt, wo die Adresse ist kein Vielfaches von 3, dann werden Sie mit .6GB Speicher, sondern verteilen sich über den Adressraum mit 2024 byte-Blöcke öffnen zwischen. Wenn Sie brauchen, um ein Objekt zu erstellen war .2GB würden Sie nicht in der Lage sein, es zu tun, denn es ist nicht ein block groß genug, um es in passen und zusätzlichen Platz nicht abgerufen werden kann (bei einer 32 bit-Umgebung). Mögliche Lösungen für dieses Problem sind Dinge wie die Verwendung von kleineren Objekten, die Verringerung der Menge an Daten, die Sie im Speicher speichern, oder mit einem Speicher-management-Algorithmus, um zu beschränken/verhindern, dass die Fragmentierung des Speichers. Es sollte angemerkt werden, dass, es sei denn, Sie entwickeln ein großes Programm, das verwendet eine große Menge an Speicher, wird dies nicht ein Problem sein. Auch dieses Problem kann auftreten, auf 64-bit-Systemen wie windows beschränkt sich hauptsächlich durch die Größe der Auslagerungsdatei und der Größe des RAM auf dem system.Da die meisten Programme verlangen Arbeitsspeicher vom OS und nicht Wunsch eine Datei zuordnen, Sie werden durch das system begrenzt die RAM und die Auslagerungsdatei. Wie bereits im Kommentar von Néstor Sánchez (Néstor Sánchez) auf dem blog, mit managed code wie C# Sie sind fest in der RAM/Auslagerungsdatei-Einschränkung und der Adressraum des Betriebssystems.
Dass war viel länger als erwartet. Hoffentlich hilft es jemanden. Ich habe es gepostet, weil ich lief in die
System.OutOfMemoryException
läuft ein x64-Programm auf einem system mit 24GB RAM, obwohl mein array war nur hält 2GB Zeug.InformationsquelleAutor der Antwort Trisped
Ich würde raten, gegen den /3GB-windows-boot-option. Abgesehen von allem anderen (es ist übertrieben, dies zu tun für eine schlecht benommen Anwendung, und es wird wahrscheinlich nicht dein problem lösen, sowieso), kann es dazu führen, eine Menge von Instabilität.
Viele Windows-Treiber sind nicht getestet mit dieser option also durchaus ein paar von Ihnen davon ausgehen, dass der Benutzermodus-Zeiger zeigen immer auf die unteren 2 GB des Adressraums. Das heißt, Sie können brechen schrecklich mit /3GB.
Windows jedoch normal-Grenze eines 32-bit-Prozess auf eine 2-GB-Adressraum.
Aber das bedeutet nicht, sollten Sie erwarten zu können, zu reservieren 2GB!
Den Adressraum ist schon übersät mit allen Arten von zugewiesenen Daten. Da ist der Stapel, und alle Assemblys, die geladen werden, statische Variablen und so weiter. Es gibt keine Garantie, dass es 800MB zusammenhängenden unzugeordneten Speicher überall.
Zuweisung von 2 400 MB große Brocken wäre wahrscheinlich besser ergehen. Oder 4 200MB Brocken. Kleinere Zuweisungen sind viel leichter zu finden Platz für Sie in einem fragmentierten Speicher.
Sowieso, wenn du gehst, um die Bereitstellung dieser für eine Maschine 12GB sowieso, Sie werden wollen, führen Sie dies als eine 64-bit-Anwendung, die sollte alle Probleme lösen.
InformationsquelleAutor der Antwort jalf
Wechsel von 32 auf 64 bit hat bei mir einen Versuch Wert, wenn Sie auf einem 64 bit pc, und es muss nicht der port.
InformationsquelleAutor der Antwort chris
Wenn Sie müssen solche großen Strukturen, vielleicht könnten Sie nutzen die Memory-Mapped-Dateien.
Dieser Artikel könnte hilfreich sein:
http://www.codeproject.com/KB/recipes/MemoryMappedGenericArray.aspx
LP
Dejan
InformationsquelleAutor der Antwort Dejan Stanič
32bit windows verfügt über eine 2 GB Prozess-Speicher-limit. Der /3GB boot-option, die andere erwähnt haben, wird dies 3GB mit nur 1 GB für die restlichen OS-kernel verwenden. Realistisch wenn Sie möchten, um mehr als 2GB ohne Hektik, dann ein 64bit OS erforderlich ist. Auch dies überwindet das problem, dass obwohl man kann 4 GB physikalischen RAM, der Adressraum requried für die Grafikkarte machen kann, eine beträchtliche Spannfutter, dass der Speicher unbrauchbar - in der Regel rund 500MB.
InformationsquelleAutor der Antwort redcalx
Eher als Zuweisung eine riesige Palette, könntest du versuchen mit Hilfe eines iterator? Diese Verzögerung ausgeführt, d.h. die Werte werden nur generiert, als Sie aufgefordert, in einer foreach-Anweisung; Sie sollten nicht mehr genügend Speicher auf diese Weise:
Den oben generieren Sie so viele Zufallszahlen wie Sie möchten, aber nur generieren, als Sie aufgefordert werden, über eine foreach-Anweisung. Sie laufen nicht aus der Erinnerung, die Art und Weise.
Abwechselnd, Wenn Sie müssen Sie haben Sie alle an einem Ort, speichert Sie in einer Datei, anstatt im Speicher.
InformationsquelleAutor der Antwort Judah Himango
Gut, ich habe ein ähnliches problem mit einer großen Datenmenge gesetzt und versucht zu zwingen, die Anwendung zu bedienen, so dass viele Daten nicht wirklich die richtige option. Der beste tip den ich dir geben kann, ist Ihre Daten verarbeiten, in kleine Brocken wenn es möglich ist. Weil der Umgang mit so viel Daten, das problem wird wieder kommen, früher oder später. Plus, können Sie nicht wissen, die Konfiguration jedes Rechners, starten Sie Ihre Anwendung, so dass es immer ein Risiko, dass die Ausnahme passiert, auf einem anderen pc.
InformationsquelleAutor der Antwort Francis B.
Ich hatte ein ähnliches problem, es wurde durch einen StringBuilder.ToString();
InformationsquelleAutor der Antwort Ricardo Rix
Konvertieren Sie Ihre Lösung für x64. Wenn Sie nach wie vor ein Problem, Zuschuss max Länge, um alles, was wirft eine Ausnahme wie unten :
InformationsquelleAutor der Antwort Samidjo
Erhöhen Sie die Windows-Prozess-Grenze auf 3gb. (via boot.ini-oder Vista-boot-manager)
InformationsquelleAutor der Antwort leppie