3 Stimmen

Java: Speicher auf die Festplatte auslagern

Nehmen wir an, ich habe eine Java-Anwendung, die ungefähr Folgendes tut:

  1. Initialisieren (dauert sehr lange, weil es kompliziert ist)
  2. Schnell ein paar Dinge erledigen
  3. Lange Zeit untätig warten (hier Ihr Lieblingsmechanismus)
  4. Gehen Sie zu Schritt 2.

Gibt es eine Möglichkeit, die JVM zu ermutigen oder zu zwingen, ihren Speicher während langer Leerlaufzeiten auf die Festplatte zu leeren? (z.B. am Ende von Schritt 2 einen Funktionsaufruf machen, der effektiv sagt "HEY JVM! Ich gehe jetzt für eine Weile schlafen.")

Es macht mir nichts aus, einen großen Teil des virtuellen Speichers zu verwenden, aber der physische Speicher ist auf dem Rechner, den ich verwende, sehr knapp, weil es viele Hintergrundprozesse gibt.

2voto

Dean J Punkte 37317

Ich denke, das Betriebssystem sollte das regeln.

Andernfalls könnten Sie Ihre Anwendung nach der Initialisierung manuell auf der Festplatte oder in einer Datenbank speichern und eine schnellere Initialisierung mit diesen Daten durchführen, vielleicht?

2voto

Asaph Punkte 153684

Anstatt Ihr Programm untätig zu lassen und Ressourcen zu verbrauchen, sollten Sie es mit cron planen. Oder noch besser, da Sie Java verwenden, planen Sie es mit Quarz ? Tun Sie Ihr Bestes, um Elemente Ihrer langwierigen Initialisierungsprozedur zwischenzuspeichern, damit Sie nicht jedes Mal, wenn die geplante Aufgabe ausgeführt wird, eine hohe Strafe zahlen müssen.

2voto

OscarRyz Punkte 189898

Als allererstes müssen Sie sicherstellen, dass Ihre Objekte garbage collectable sind. Aber das ist nur der erste Schritt.

Zweitens kann es sein, dass der von der JVM verwendete Speicher gar nicht an das Betriebssystem zurückgegeben wird.

Zum Beispiel. Nehmen wir an, Sie haben 100 MB Java-Objekte, dann ist Ihre VM ca. 100 MB groß. Nach der Garbage Collection können Sie die Heap-Nutzung auf 10 MB reduzieren, aber die VM wird in etwa bei 100 MB bleiben. Diese Strategie wird angewandt, damit die VM Speicher für neue Objekte zur Verfügung hat.

Damit die Anwendung "physischen" Speicher an das System zurückgeben kann, müssen Sie prüfen, ob Ihre VM dies unterstützt.

Es gibt zusätzliche VM-Optionen que Mai ermöglichen es Ihrer Anwendung, mehr Speicher an das Betriebssystem zurückzugeben:

-XX:MaxHeapFreeRatio=70 Maximaler Prozentsatz des freien Heaps nach der GC, um ein Schrumpfen zu vermeiden.

-XX:MinHeapFreeRatio=40 Minimaler Prozentsatz des nach der GC freien Heaps, um eine Expansion zu vermeiden.

Nach meiner Interpretation dieser Optionen wird sich der VM drücken, wenn er unter 70 % fällt. Aber ehrlich gesagt weiß ich nicht, ob nur der Heap schrumpfen wird y an das Betriebssystem zurückgegeben werden oder nur schrumpfen innerhalb die VM.

Eine vollständige Beschreibung der Speicherverwaltung im laufenden Betrieb finden Sie hier:

Beschreibung von HotSpot GCs: Speicherverwaltung in der Java HotSpot Virtual Machine White Paper: https://www.oracle.com/technetwork/java/javase/memorymanagement-whitepaper-150215.pdf

Und bitte, bitte. Probieren Sie es aus, messen Sie und lassen Sie uns wissen, ob sich der Speicherverbrauch dadurch tatsächlich verringert.

1voto

deeringc Punkte 178

Es ist ein bisschen wie ein Hack, um das Mindeste zu sagen, aber angenommen, Sie arbeiten mit Win32 und sind bereit, die Portabilität aufzugeben - schreiben Sie eine kleine DLL, die SetProcessWorkingSetSize und rufen es mit JNI auf. Dies ermöglicht es Ihnen vorschlagen dem Betriebssystem mitzuteilen, wie groß der WS sein soll. Sie können sogar -1 angeben, in diesem Fall wird das Betriebssystem versuchen, so viel wie möglich auszulagern.

0voto

Chinmay Kanchi Punkte 58341

Angenommen, dies ist so etwas wie ein Server, der auf eine Anfrage wartet, könnten Sie dies tun?

  1. Erstellen Sie zwei Klassen, Server und Worker.
  2. Der Server hört nur zu und startet den Worker bei Bedarf.
  3. Wenn Worker noch nie initialisiert wurde, initialisieren Sie ihn.
  4. Nachdem der Worker seine Aufgaben erledigt hat, serialisieren Sie ihn, schreiben ihn auf die Festplatte und setzen das Worker-Objekt auf null.
  5. Warten Sie auf eine Anfrage.
  6. Wenn eine Anfrage eingeht, lesen Sie das serialisierte Worker-Objekt von der Festplatte und laden es in den Speicher.
  7. Worker-Aufgaben ausführen, nach Abschluss serialisieren, ausschreiben und Worker-Objekt auf null setzen.
  8. Ausspülen und wiederholen.

Das bedeutet, dass das speicherintensive Worker-Objekt aus dem Speicher entladen wird (wenn der gc das nächste Mal ausgeführt wird, und Sie können den gc durch den Aufruf von System.gc() zum Ausführen veranlassen, nachdem Sie das Worker-Objekt auf null gesetzt haben), aber da Sie seinen Zustand gespeichert haben, können Sie ihn von der Festplatte neu laden und ihn seine Arbeit tun lassen, ohne die Initialisierung erneut zu durchlaufen. Wenn er alle "x" Stunden ausgeführt werden muss, können Sie einen java.util.Timer in die Serverklasse einfügen, anstatt auf einen Socket zu hören.

EDIT: Es gibt auch eine JVM-Option -Xmx, die die maximal Größe des Heaps der JVM. Dies ist wahrscheinlich nicht hilfreich in diesem Fall, aber ich dachte nur, ich würde es in dort werfen.

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