19 Stimmen

JVM Garbage Collection und eine Paging-Speicherarchitektur

In den letzten 10 Jahren, in denen ich über Java und/oder Garbage Collection diskutiert habe, war die einzige Leistungseinbuße, die ich nicht verteidigen konnte, die Tatsache, dass der Garbage-Collection-Algorithmus mehr oder weniger bricht, wenn er in einer Paged-Memory-Architektur läuft und Teile des Heaps ausgelagert werden.

Unix-Systeme (und insbesondere Linux) paginieren Speicher, der eine Zeit lang nicht benutzt wurde, aggressiv aus, und während das für eine durchschnittliche undichte C-Anwendung gut ist, wird die Leistung von Java in Situationen mit wenig Speicher beeinträchtigt.

Ich weiß, dass die beste Praxis darin besteht, den maximalen Heap kleiner zu halten als den physischen Speicher. (Oder Sie werden sehen, wie Ihre Anwendung zu Tode swappt), aber die Idee - zumindest in der Unix-Welt - ist, dass der Speicher besser für Dateisystem-Caches usw. verwendet werden könnte.

Meine Frage ist: Gibt es irgendwelche Paging (bewusst) Garbage Collecting Algorithmen?

9voto

kdgregory Punkte 37614

Ich behaupte, dass dies nicht so ein großes Problem ist, wie Sie denken.

Um sicherzugehen, dass wir dasselbe beschreiben: Eine vollständige Sammlung erfordert, dass die JVM den Objektgraphen durchläuft, um jedes erreichbare Objekt zu identifizieren; die übrig gebliebenen sind Müll. Dabei berührt sie jede Seite im Heap der Anwendung, was dazu führt, dass jede Seite in den Speicher ausgelagert wird, wenn sie ausgelagert wurde.

Ich denke, das ist aus mehreren Gründen unbedenklich: Erstens, weil moderne JVMs Generationskollektoren verwenden und die meisten Objekte nie ihren Weg aus den jungen Generationen finden, die fast garantiert in der residenten Menge sind.

Zweitens, weil auf die Objekte, die aus der jungen Generation auswandern, noch häufig zugegriffen wird, was wiederum bedeutet, dass sie in der residenten Menge enthalten sein sollten. Dies ist ein eher schwaches Argument, und es gibt tatsächlich viele Fälle, in denen langlebige Objekte nur von der GC berührt werden (ein Grund, warum ich nicht an speicherbegrenzte Caches glaube).

Der dritte Grund (und es gibt vielleicht noch mehr) ist, dass die JVM (zumindest die Sun JVM) einen Mark-Sweep-Compact Collector verwendet. Nach der GC belegen die aktiven Objekte im Heap also eine geringere Anzahl von Seiten, was wiederum die RSS erhöht. Dies ist übrigens der Hauptgrund dafür, dass Swing-Anwendungen explizit System.gc() aufrufen, wenn sie minimiert werden: Durch die Verdichtung des Heaps muss weniger ausgetauscht werden, wenn sie wieder maximiert werden.


Beachten Sie auch, dass die Heap-Fragmentierung von C/C++-Objekten extrem sein kann und dass junge Objekte unter ältere gestreut werden, so dass die RSS größer sein muss.

5voto

Sebastien Loisel Punkte 66

Sie haben recht, der Garbage Collector und der virtuelle Speichermanager müssen zusammenarbeiten, da sonst der GC das System zerstört. Eine solche Zusammenarbeit zwischen GC und Kernel wurde von Matthew Hertz, Yi Feng und Emery D. Berger untersucht. Um eine gute Leistung zu erzielen, mussten sie den Kernel leicht erweitern und auch den Garbage Collector optimieren.

Unter hohem Speicherdruck benötigte ihr Benchmark mit der GenMS Java GC etwa 160x länger. Mit der neuen, seitenbasierten GC war der Benchmark nur 1,6 Mal langsamer. Mit anderen Worten, mit einer richtig abgestimmten GC gibt es einen 100-fachen Leistungsgewinn.

http://lambda-the-ultimate.org/node/2391

4voto

Steve Jessop Punkte 264569

Ich bin kein Experte, aber jede Art von generativer Garbage Collection sollte etwas helfen. Die Seiten, die aggressiv ausgetauscht werden, enthalten wahrscheinlich eher ältere Objekte als neuere, so dass die Garbage Collection sie natürlich weniger häufig berührt.

Ich würde auch die Gegenfrage stellen: Gibt es irgendwelche Unix-Paging-Algorithmen, die Müllsammlungen berücksichtigen? Wenn eine bestimmte Seite regelmäßig (wenn nicht sogar häufig) in den Speicher geschleppt wird, dann ist sie vielleicht doch kein so guter Kandidat, um zugunsten von mehr Plattencache entsorgt zu werden ;-)

4voto

John Feminella Punkte 292907

Unix-Systeme (und insbesondere Linux) paginieren Speicher, der eine Zeit lang nicht benutzt wurde, aggressiv aus, und während das für eine durchschnittliche undichte C-Anwendung gut ist, wird die Leistung von Java in Situationen mit wenig Speicher beeinträchtigt.

Beachten Sie, dass es sich hierbei in der Regel um eine einstellbare Einstellung handelt - vm.swappiness für den Linux-Kernel zum Beispiel. Sie können lesen einen Blog-Artikel, den ich zu diesem Thema geschrieben habe wenn Sie tiefer gehende Informationen über Swap-Tuning unter Linux wünschen.

Gibt es Algorithmen, die das Auslagern von Speicherplatz berücksichtigen?

Algorithmen für die Müllabfuhr sind in der Regel für eine Vielzahl möglicher Programme als Eingabe und für den Betrieb in einer großen Anzahl möglicher Umgebungen ausgelegt; dies muss bei ihrer Entwicklung berücksichtigt werden. Ich denke, es wäre eine echte Herausforderung, einen "paging-aware" gc-Algorithmus zu entwickeln, der für alle nützlich ist. Wenn man einen Algorithmus für eine sehr spezialisierte Umgebung schreibt, in der man die Dinge einschränken kann, dann denke ich, dass man eine ziemlich gute Chance hat, ein gutes Ergebnis zu erzielen.

0voto

Tom Hawtin - tackline Punkte 142461

In der heutigen Zeit ist das Auslagern von Programmen eine wirklich schlechte Idee. Speicher ist sehr billig.

FWIW, wenn Sie auf einem PC von einem Hersteller laufen, der gerne ein Vielfaches des Preises für Arbeitsspeicher verlangt, hat Windows Vista einen prädiktiven Auslagerungsalgorithmus, der recht gut funktioniert (vielleicht das Einzige, was dieses Betriebssystem gut macht).

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