79 Stimmen

Ist "Speicherplatzmangel" ein behebbarer Fehler?

Ich programmiere schon sehr lange, und die Programme, die ich sehe, wenn ihnen der Speicher ausgeht, versuchen aufzuräumen und sich zu beenden, d.h. sie scheitern mit Anstand. Ich kann mich nicht erinnern, wann ich das letzte Mal gesehen habe, dass ein Programm tatsächlich versucht hat, sich zu erholen und normal weiterzuarbeiten.

Ein so großer Teil der Verarbeitung hängt davon ab, dass Speicher erfolgreich zugewiesen werden kann, insbesondere in Sprachen mit Garbage-Collector, dass Fehler außerhalb des Speichers als nicht wiederherstellbar eingestuft werden sollten. (Zu den nicht wiederherstellbaren Fehlern gehören Dinge wie Stapelüberläufe.)

Welches zwingende Argument spricht dafür, dass es sich um einen anfechtbaren Fehler handelt?

39voto

Jon Skeet Punkte 1325502

Das hängt wirklich davon ab, was Sie bauen wollen.

Es ist nicht völlig unvernünftig, dass ein Webserver ein Anfrage/Antwort-Paar nicht beantworten kann, aber dann für weitere Anfragen weitermacht. Man müsste allerdings sicherstellen, dass der einzelne Fehler keine nachteiligen Auswirkungen auf den globalen Zustand hat - das wäre das Schwierige daran. In Anbetracht der Tatsache, dass ein Fehler in den meisten verwalteten Umgebungen (z. B. .NET und Java) zu einer Ausnahme führt, vermute ich, dass die Ausnahme, wenn sie im "Benutzercode" behandelt wird, für künftige Anforderungen wiederhergestellt werden kann - wenn z. B. eine Anforderung versucht, 10 GB Speicher zuzuweisen, und dies fehlschlägt, sollte dies dem Rest des Systems nicht schaden. Wenn dem System jedoch der Speicher ausgeht, während es versucht, die Anforderung an den Benutzercode weiterzuleiten, könnte das noch schlimmer sein.

18voto

Aaron Digulla Punkte 308693

In einer Bibliothek wollen Sie eine Datei effizient kopieren. Dabei stellt man in der Regel fest, dass das Kopieren einer kleinen Anzahl großer Chunks viel effektiver ist als das Kopieren vieler kleiner Chunks (z. B. ist es schneller, eine 15-MB-Datei zu kopieren, indem man 15 1-MB-Chunks kopiert, als 15'000 1K-Chunks).

Der Code funktioniert jedoch mit jeder Stückchengröße. Auch wenn es mit 1 MB großen Chunks schneller geht, kann es sinnvoll sein, OutOfMemoryError abzufangen und die Chunk-Größe zu reduzieren, bis Sie Erfolg haben, wenn Sie ein System entwickeln, in dem viele Dateien kopiert werden.

Ein anderer Ort ist ein Cache für Objekte, die in einer Datenbank gespeichert sind. Sie möchten so viele Objekte wie möglich im Cache halten, aber den Rest der Anwendung nicht beeinträchtigen. Da diese Objekte neu erstellt werden können, ist es eine kluge Art, den Cache mit einem Handler zu verbinden, der Einträge aus dem Speicher löscht, bis der Rest der Anwendung wieder genug Platz zum Atmen hat.

Schließlich möchten Sie bei der Bildbearbeitung so viel wie möglich vom Bild in den Speicher laden. Auch hier ermöglicht ein OOM-Handler die Implementierung, ohne im Voraus zu wissen, wie viel Speicher der Benutzer oder das Betriebssystem Ihrem Code zugestehen werden.

[EDIT] Beachten Sie, dass ich hier von der Annahme ausgehe, dass Sie der Anwendung eine feste Menge an Speicher zugewiesen haben und diese Menge kleiner ist als der gesamte verfügbare Speicher ohne Swap-Bereich. Wenn Sie so viel Speicher zuweisen können, dass ein Teil davon ausgelagert werden muss, machen einige meiner Kommentare keinen Sinn mehr.

11voto

MATLAB-Anwendern geht beim Rechnen mit großen Arrays immer wieder der Speicher aus. Wenn zum Beispiel die Variable x in den Speicher passt und "x+1" ausgeführt wird, weist MATLAB dem Ergebnis Speicherplatz zu und füllt ihn dann. Wenn die Zuweisung fehlschlägt, gibt MATLAB eine Fehlermeldung aus und der Benutzer kann etwas anderes versuchen. Es wäre eine Katastrophe, wenn MATLAB sich jedes Mal beenden würde, wenn dieser Anwendungsfall auftritt.

8voto

Ifeanyi Echeruo Punkte 787

OOM sollte wiederherstellbar sein, denn das Herunterfahren ist nicht die einzige Strategie, um sich von OOM zu erholen.

Für das OOM-Problem auf der Anwendungsebene gibt es eigentlich eine ziemlich standardisierte Lösung. Legen Sie im Rahmen des Anwendungsdesigns eine sichere Mindestmenge an Speicher fest, die erforderlich ist, um einen Zustand ohne Speicher wiederherzustellen. (z. B. der Speicher, der zum automatischen Speichern von Dokumenten, zum Aufrufen von Warndialogen und zum Protokollieren von Abschaltdaten erforderlich ist).

Weisen Sie zu Beginn Ihrer Anwendung oder zu Beginn eines kritischen Blocks diese Menge an Speicher im Voraus zu. Wenn Sie feststellen, dass der Speicher nicht ausreicht, geben Sie den Schutzspeicher frei und führen die Wiederherstellung durch. Die Strategie kann immer noch fehlschlagen, aber im Großen und Ganzen bietet sie ein hervorragendes Preis-Leistungs-Verhältnis.

Beachten Sie, dass die Anwendung nicht heruntergefahren werden muss. Sie kann einen modalen Dialog anzeigen, bis die OOM-Bedingung behoben ist.

Ich bin mir nicht 100%ig sicher, aber ich bin mir ziemlich sicher. Code vollständig ' (Pflichtlektüre für jeden seriösen Software-Ingenieur) behandelt dies.

P.S. Sie können Ihr Anwendungs-Framework erweitern, um diese Strategie zu unterstützen, aber bitte implementieren Sie eine solche Richtlinie nicht in einer Bibliothek (gute Bibliotheken treffen keine globalen Entscheidungen ohne die Zustimmung der Anwendung).

5voto

n-alexander Punkte 13553

Ich arbeite an einem System, das Speicher für den IO-Cache zuweist, um die Leistung zu erhöhen. Wenn es dann OOM feststellt, nimmt es einen Teil davon zurück, damit die Geschäftslogik fortgesetzt werden kann, auch wenn das weniger IO-Cache und eine etwas geringere Schreibleistung bedeutet.

Ich habe auch mit einer eingebetteten Java-Anwendung gearbeitet, die versuchte, OOM zu verwalten, indem sie die Garbage Collection erzwang und optional einige unkritische Objekte freigab, z. B. vorab abgerufene oder zwischengespeicherte Daten.

Die Hauptprobleme bei der OOM-Behandlung sind:

1) die Möglichkeit, den Versuch an der Stelle zu wiederholen, an der der Fehler aufgetreten ist, oder die Möglichkeit, zurückzugehen und den Versuch von einem höheren Punkt aus zu wiederholen. Die meisten modernen Programme verlassen sich zu sehr auf die Sprache, um einen Wurf auszuführen, und verwalten nicht wirklich, wo sie landen und wie sie die Operation erneut versuchen können. In der Regel geht der Kontext der Operation verloren, wenn er nicht dafür ausgelegt ist, erhalten zu bleiben.

2) in der Lage zu sein, tatsächlich etwas Speicher freizugeben. Dies bedeutet eine Art Ressourcenmanager, der weiß, welche Objekte kritisch sind und welche nicht, und dass das System in der Lage ist, die freigegebenen Objekte erneut anzufordern, wenn sie später kritisch werden

Ein weiterer wichtiger Punkt ist die Möglichkeit, ein Rollback durchzuführen, ohne eine weitere OOM-Situation auszulösen. Dies ist etwas, das in höheren Sprachen schwer zu kontrollieren ist.

Außerdem muss sich das zugrunde liegende Betriebssystem in Bezug auf OOM vorhersehbar verhalten. Bei Linux ist dies beispielsweise nicht der Fall, wenn Memory Overcommit aktiviert ist. Viele Swap-fähige Systeme werden eher sterben, als dass sie den OOM an die betreffende Anwendung melden.

Und es gibt den Fall, dass es nicht Ihr Prozess ist, der die Situation verursacht hat, so dass das Freigeben von Speicher nicht hilft, wenn der beleidigende Prozess weiterhin leckt.

Aus diesem Grund sind es oft die großen und eingebetteten Systeme, die diese Techniken anwenden, da sie die Kontrolle über Betriebssystem und Speicher haben, um sie zu ermöglichen, und die Disziplin/Motivation, sie zu implementieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X