System.gc() - Nicht benutzen bei Multiprocessing - Warum?

rpiontek

Grünschnabel
Hi,

mir ist gesagt worden, wenn das Programm über mehrere
Prozessoren verteilt wird, soll nicht System.gc() im Code
benutzt werden, auch wenn man alles synchronisiert (Multithreading)
hat.

Soll zur Speicher-Inkosistenz kommen können...

Warum?

Gruß
 
Laut Thomas soll man gc() wenn möglich überhaupt nicht aufrufen:
http://www.tutorials.de/forum/1256132-post5.html

Immerhin macht der GC ja auch ohne das gute Arbeit, mir ist (außer im Falle eines Bugs) noch nie der RAM ausgegangen. Und man kann per Parameter der VM ja auch sagen, dass sie mehr RAM für sich reservieren soll:

Code:
-Xmx-IrgendEineZweierpotenz-m

Natürlich ohne den 2. und 3. Minus.
 
Was Thomas geschrieben hat, wußte ich bereits.
-Xmx.... kenne ich auch...
Die Frage war, wann kann zur Speicher-Inkosistenz kommen
wegen System.gc() bei Verteilung über mehrere Processoren....

Oder ob es überhaupt sein kann...
 
Hallo,

also das ganze hört sich für mich eher nach einer Urban Legend an. Als allgemeingültige Aussage würde ich es stark anzweifeln.

Mal davon abgesehen, das System.gc() nicht garantiert anläuft, weil das eine Entscheidung der VM ist - wenn es denn anläuft (was meist der Fall ist), macht es nichts anderes als eine "normale" Major Collection, also die Bereinigung von Young und Tenured Space mit den jeweils dafür eingestellten Collectoren. Je nach Häufigkeit des Aufrufs von System.gc() und abhängig von den eingestellten Collectoren kann das schon mal auf die Performance gehen ;), aber nicht zu Speicherinkonsistenzen führen.

Wenn es also Speicherinkonsistenzen gibt, müssten die auch ohne Aufruf von System.gc() auftreten.

Hast Du vielleicht noch ein paar mehr Informationen zu der Aussagen (VM-Version, eingestellte Collectoren ect)? Man soll ja niemals nie sagen ...

Viele Grüße
THMD
 
Hm... ich vermute, dass die GC in dem Thread läuft in dem System.gc(); gerufen wird. Besonders für eine Full GC ist es notwendig, dass der komplette Thread kurz stillsteht um die Referenzen durchzugehen. Wenn nun währenddessen ein anderer Thread auf Daten des Threads zugreift in dem die GC läuft, kann das sicher zu Inkosistenzen führen. Eine automatische GC wird ja dagegen von der VM ausgelöst, die genau weiß, welche Threads anzuhalten sind.

Das ist wie gesagt nur ne Vermutung basierend auf meinem rudimentären Halbwissen bzgl. Speichermanagement + ein paar (hoffentlich) logische Schlussfolgerungen... ;)

Gruß
Ollie
 
Hallo,

es gibt je nach verwendetem GC-Algo einen oder mehreren GC Threads
(Parallel GC, Beispielsweise Concurrent Mark and Sweep (CMS)).
Wird System.gc() aus Anwendungscode aus aufgerufen, so wird
intern ein GC Request eingestellt. Die JVM bekommt also einen
Hinweis bei der nächsten möglichen Gelegenheit einen GC zu machen.
Dieser GC lauft dann in einem der GC Threads ab. Nicht auf in dem
Thread, der System.gc() aufgerufen hat.

Weiterhin bleiben bei einem Stop-the-World GC Vorgang "alle" Threads
(außer die für den GC) stehen. Nicht nur einer ;-).

Um festzustellen, welche Objekte der GC aus dem Speicher entfernen kann, schaut
er nach welche Objekte noch von einem Thread aus direkt (oder auch indirekt)
referenziert werden können. Je nach GC Algo werden nun die nicht mehr erreichbaren
Objekte direkt weggeräumt, oder markiert und anschließend beim nächsten Durchlauf
freigegeben.

Je nach verwendeten GC Algo muss zum Analysieren des Systemzustandes ein Snapshot erstellt werden.
Das ist natürlich viel einfacher wenn alle Threads gestoppt werden (stop-the-world).

Es gibt aber auch (sehr komplizierte) GC Algorithmen welche die Stop the World Zeiten
sehr klein halten oder gar ganz eliminieren können.

Die Frage ob ein explizites System.gc() bei Mehrprozessor- / Mehrkernsystem
zu Problemen führt kann ich mit jein beantworten, wobei mir bezüglich korruptem
Speicher noch nichts untergekommen ist.

Ein explizites System.gc() kann unter umständen die Performance der Anwendung
erheblich verschlechten. Heute GCs arbeiten in der Regel sehr zuverlässig und sind
selbst adaptiv. D.h. sie steuern ihren Einsatz selbst. Was hochperformante GC Operationen
ermöglict. Greift der Anwender nun mit einer Folge von manuellen System.gc() aufrufen
dazwischen so bringt er dieses selbstorganisierende System aus dem tritt und schon wird
u.U. ein Full-GC gemacht, welcher 1) absolut unnötig ist und 2) das System ausbremst.

Gruß Tom
 
@Thomas ...Dein Wisssen ist enorm... Genial... Moin nach Saarland...


@Alle ... Danke für die Antworten und so schnell...

Also ichg hatte mit Massen-Daten gearbeitet, mit extrem
langen Laufzeiten. Da war jede Performance von enorma
Wichtigkeit.

Wenn System.gc() dann es enorm verschlechtert ist es
ein sehr wichtiger Faktor.

Zitat:
# Es gibt aber auch (sehr komplizierte) GC Algorithmen welche die Stop the World Zeiten
# sehr klein halten oder gar ganz eliminieren können.


Ich bin mir nicht sicher, ob du mit der Aussage meinst, dass es bei einem der
GC Algorithmus sein kann, dass er vielleicht nicht alle Threads
stoppt/betrachtet. Vielleicht auch durch Mehrprozessor- / Mehrkernsystem.



Aber es war schon sehr hilfreich....
 
Hallo,

Zitat:
# Es gibt aber auch (sehr komplizierte) GC Algorithmen welche die Stop the World Zeiten
# sehr klein halten oder gar ganz eliminieren können.


Ich bin mir nicht sicher, ob du mit der Aussage meinst, dass es bei einem der
GC Algorithmus sein kann, dass er vielleicht nicht alle Threads
stoppt/betrachtet. Vielleicht auch durch Mehrprozessor- / Mehrkernsystem.
alle GC-Collectoren betrachten immer alle Threads einer VM. Irgendwann macht jeder Collector eine (oder mehrere) Stop-the-World Pause. Ich kenne zumindest auf der Sun-VM keinen der das nicht macht (selbst der neue G1 Collector macht eine Pause). Je nach Collector-Typ dauert diese Pause halt länger oder kürzer.

Schau dir doch mal die Doku (http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html) von Sun zu dem Thema GC-Tuning an. Die beantwortet eigentlich relativ viele Fragen zu den Collectoren und Einstellmöglichkeiten.

Unter http://blogs.sun.com/jonthecollector/entry/our_collectors findest du eine relativ gute Übersicht, welche Collectoren zusammenarbeiten und ein paar Infos zu dem neuen G1 Collector.

Grüße
THMD
 
Hallo,

auf http://edocs.bea.com/jrockit/geninfo/diagnos/garbage_collect.html
findet man auch Erklärungen zu einzelnen GC Verfahren (allgemein, sowie speziell für BEAs JRockIT JVM).

BEA und zahlreiche andere JVM Hersteller bieten unterstützen auch ein deterministische GC, so dass bei dem Zeiträume definieren kann in denen auf keinen Fall ein GC gemacht werden soll. Das ist wichtig für Awendungen mit Realtime-Anforderung.
Eine andere Möglichkeit (Soft)-Realtime zu unterstützen ist es die GC Zeiten unter einer granatierten Schranke zu halten. Das klappt mit entsprechend ausgefeilten GC Algos auch ganz gut. In dem Zusammenhang ist mir auch noch zero-pause GC ein Begriff, aber ich kann irgendwie keine passende Präsentation / Artikel mehr dazu finden.

Siehe auch:
http://www.bea.com/content/news_events/white_papers/BEA_JRockit_Deterministic_GC_wp.pdf
Gruß Tom
 
Zurück