2009-05-07 6 views
6

Das Problem ist einfach Ich habe einen Prozess, der ETL auf einigen XML-Dateien tut. Wir haben wirklich große XML-Dateien bekommen und ich habe OutOfMemoryExceptions bekommen.Wie man einen .NET-Prozess aus dem Speicher laufen lässt, ohne den gesamten Systemspeicher zu erschöpfen

Das Fixieren des Prozesses ist relativ einfach. Ich möchte jedoch einen Komponententest für meine NUnit-Suite machen, um sicherzustellen, dass der Prozess auch weiterhin mit wirklich großen Dateien umgehen kann. Wenn ich jedoch den Arbeitsspeicher meiner Entwicklungs-Workstation nicht mehr benötige, wird mein Rechner langsamer und zeitaufwendiger. Es ist auch keine gute Idee, eine riesige Testdatei in der Versionskontrolle zu speichern. Wenn ich einen Prozess künstlich begrenzen könnte, Thread oder Anwendungsdomäne nur eine feste Menge RAM verwenden, sagen wir 128 MB, könnte ich einen kleineren Komponententest machen, der meine Workstation nicht in die Knie zwingen würde.

Irgendwelche Vorschläge? Ist ihre nicht verwaltete API kann ich P/Invoke?

+0

ich nicht setzen in meinem Haupt-Antwort aktivieren möchten, weil es nicht genau ist Ihre Frage zu beantworten, aber das klingt wie eine seltsame Sache zu Unit-Test. Auf einer hohen Ebene behandelt entweder Ihr Algorithmus zum Lesen der Dateien sehr große Dateien beliebiger Größe (weil sie die Datei streamen oder chunks) oder nicht. Das wird sich nicht oft ändern, wenn überhaupt, und ich sehe nicht, was Sie davon haben, es jedes Mal mit Ihrer Testsuite zu testen, besonders angesichts der Tatsache, dass es (wenn es scheitert) nicht jedes Mal zuverlässig versagen kann Datei. – mquander

+0

Ich öffne und scanne die Datei mehrmals. Manchmal mache ich es als Stream, manchmal nicht. 99,9% der gescannten Dateien sind klein genug, um die gesamte Datei in den Speicher zu laden. Die anderen .01% müssen verarbeiten. Wenn ich also alle Dateioperationen stream-basiert mache (das Problem behebend), könnte jemand einen neuen Schritt hinzufügen, der die Datei verarbeitet, indem sie alles in den Speicher lädt. Ohne einen Komponententest, der die gesamte ETL-Operation für eine Datei ausführt, die groß genug ist, um den Verarbeitungs-RAM zu essen, wird dies in die Produktion übergehen, da QA das System möglicherweise nicht mit einer wirklich großen Datei testen kann. –

+0

Ich denke, dass die beste Antwort hier ist, die Operationen zu kapseln, die man sehr gut machen muss, so dass es für jeden anderen unmöglich ist, den Pfad der Datei zu umgehen und das Ganze zu öffnen, um etwas zu holen. Natürlich könnte jemand immer noch durch deinen Dschungel hacken, um die ganze Akte zu öffnen, wenn sie es hart genug versuchen, aber ich denke, dass du jemanden aus reiner Unwissenheit daran hindern kannst, es zu tun. (Ich weiß, dass dies zur Diskussion darüber, wie man es testet, nebenbei ist, aber Prävention ist die beste Heilung.) – mquander

Antwort

0

Ich verstehe nicht ganz, was Sie hier bekommen. Angenommen, Sie haben eine künstlich kleine "Testumgebung" erstellt, die keine großen Speicherbereiche zuordnen konnte, sodass OutOfMemoryExceptions auf kleinere Dateien übertragen wurden. Was hast du gewonnen? Der Komponententest sollte testen, ob Sie mit größeren Dateien auf einem echten System umgehen können, oder?

Die wichtige Sache ist vermutlich, dass Sie Dateien "so groß wie sie sein müssen" auf jedem System, auf dem sie laufen werden, behandeln, und es gibt keine echte Möglichkeit zum Komponententest außerhalb des Ausprobierens dieser Datei auf diesem System.

(Eine kleinere, weniger wichtige Sache könnte sein, ob Sie elegant mit OutOfMemoryException umgehen, aber Sie brauchen nicht wirklich nicht genug Speicher zu haben, um das zu testen; machen Sie einfach Ihre Methode eine Ausnahme gelegentlich werfen und beobachten Sie das es tut das Richtige.)

+0

Der Test ist, dass das System arbitrarly große Dateien, nicht wirklich große Dateien behandeln kann. Mit anderen Worten, alle Dateioperationen werden ausgeführt, ohne dass die gesamte Datei in den Speicher geladen wird, und es sollte keine Begrenzung geben, wie groß eine Datei sein könnte, mit der das System umgehen könnte. –

2

Kannst du nicht ein Mocking-Framework für die Speicherzuweisung verwenden und es werfen OutOfMemoryException als einen der Tests?

Allerdings, wenn Sie wirklich keinen Speicher mehr haben, gibt es nicht viel, was Ihre Anwendung sicher tun kann, aber wenn Sie zumindest elegant scheitern können, werden Ihre Benutzer dankbar sein.

Ein Beispiel: Ich hatte einen Fall in einem früheren Job, wo wir 3D-Modelle von Fabriken in Echtzeit angezeigt wurden. Die Modelle wurden so groß, dass wir, wenn wir Texturen laden wollten, keine Speicherausfälle mehr hatten. Wir haben es geschafft, die Anwendung am Leben zu erhalten und zu rendern, indem wir dafür sorgten, dass der Code mit Null-Zeigern zurechtkam, obwohl der Rest des Codes dachte, dass dort Textur-Informationen sein sollten.

+0

Ich wollte nur das Gleiche bezüglich Mock-Objekten vorschlagen. – RichardOD

1

Mocking ist am besten. Ein OOM anzuheben ist definitionsgemäß kein Unit Test. Wenn es sich um Speicher handelt, handelt es sich um Lasttests. Wenn Sie die Links am Ende dieser E-Mail lesen, werden Sie feststellen, dass echte OOMs in den besten Fällen schwer zu reproduzieren und zu debuggen sind. Eine erfundene OOM-Ausnahme ist nicht die wahre Ursache der Ausnahme und daher nicht interessanter als ein Mock zum Testen.

Stick mit einem Unit-Test mit einem Mock für die Validierung. Wenn Sie immer noch OOMs erhalten, werfen Sie mehr Arbeitsspeicher auf Ihren Server und lassen Sie Ihren Prozess häufiger recyceln/neu starten.

Hier ist ein paar interessante Informationen zu OutMemoryExceptions, die ich beim letzten Mal gesammelt habe, als ich mit ihnen gekämpft habe. Zusammenfassung: OOMs treten auf, wenn das System den von Ihnen angeforderten Betrag nicht zuordnen kann - was nicht bedeutet, dass Sie nicht genügend Arbeitsspeicher haben.

+0

"Wenn Sie immer noch OOMs erhalten, werfen Sie mehr Arbeitsspeicher auf Ihren Server und lassen Sie Ihren Prozess häufiger recyceln/neu starten." Das Hinzufügen von mehr Speicher hat keinen Einfluss auf das Problem ... er verliert dabei den virtuellen Speicher. Physischer Speicher ist nicht das Problem. Unter der Annahme, dass Sie auf einer 32-Bit-Plattform ausgeführt werden, haben Sie 2 GB für den Anwendungsadressraum, den Sie über Heaps und den Stack zuweisen können. OOMs treten auf, wenn Sie nicht genügend zusammenhängende Speicher im Adressraum zuordnen können. –

0

Es ist ziemlich einfach, in einem Prozess, der Speicher Ausnahmen zu verursachen.

Erstellen Sie einfach eine Schleife, die Speicher in Blöcken zuweist, die klein genug sind, um nicht auf dem großen Objekt-Heap zu sein (aber nicht zu viele, die die Ausnahme verursachen) und dann können Sie versuchen, eine kleinere Datei zu öffnen Das Öffnen der Datei wird dazu führen, dass nicht genügend zusammenhängender Speicher zugeordnet werden kann, und Sie erhalten Ihre OOM-Ausnahme, wenn Sie Ihre Datei öffnen, ohne eine große Datei zu benötigen. So etwas wie dies ...

List<byte[]> items = new List<byte[]>(); 
for (int i = 0; i < 10000; i++) 
{ 
    byte[] c = new byte[160000]; 
    items.Add(c); 
} 

byte[] next = new byte[1000000000]; 

Wenn Sie den obigen Code wie ausgeführt wird, erhalten Sie eine OOM Ausnahme der letzten Zeile erhalten. Aber wenn Sie die Schleife zuerst auskommentieren, wird sie ohne Fehler ausgeführt. Sie werden wahrscheinlich die Schleife ein wenig zwicken müssen, um zu erreichen, dass Ihre Datei jedes Mal fehlschlägt, aber Sie können es tun. Führen Sie einfach die Schleife vor dem Aufruf aus, um Ihre Datei in Ihrem Test zu öffnen, und Sie werden einen großen Speicherblock belegt haben, und Ihr Öffnen sollte fehlschlagen.

Sie könnten auch in die Einstellung des/3GB-Schalters schauen, wenn es eine Option für Sie ist. Es ist nicht immer die richtige Antwort und es hat Nachteile, aber es ändert sich die virtuelle Speicheraufteilung von 2 GB/2 GB auf 1 GB/3 GB, wodurch Ihr Prozess Zugriff auf mehr virtuellen Adressraum hat. Dies gibt Ihnen ein wenig mehr Spielraum in der Größe der Dateien, die Sie öffnen können. Auch hier sollten Sie über die Nachteile dieses Vorgehens nachlesen, bevor Sie nach einer Lösung suchen und sicherstellen, dass es sich lohnt, wenn es Ihrer Situation hilft.

Here ist, wie es auf dem Server diese

Verwandte Themen