[Java]GC Optimierungen

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Milbret
Beiträge: 827
Registriert: 26.05.2008 12:04:54
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Nörten-Hardenberg
Kontaktdaten:

[Java]GC Optimierungen

Beitrag von Milbret » 09.06.2010 12:51:12

Hallo,
ich habe eine Anwendung in Java entwickelt die sich mit dem Thema Dateisynchronisation befasst.
Leider ist der Speicherverbraucht, wegen der nötigen Rekurssion durch die Ordner, entsprechend groß.
Als "Lösung" mache ich nach dem abarbeiten eines Quell- und Zielpaares einfach ein System.gc()
Dies räumt wieder speicher frei, dies ist nicht gerade die eleganteste Lösung.

Deshab habe ich mich etwas zu dem Thema Java und dem GC eingelesen.
Es gibt für das Programm java auch entsprechende Parameter.
Leider weiß ich nicht genau, was der genaue unterschied zwischen den unterschiedlichen GCs sein soll.

Da der Speicher durch kurzlebige Objekte wie die Strings der absoluten Dateipfaden sowie mit Threads ordentlich verschlungen wird, wollte ich mal wissen ob es dafür einen guten GC gibt.
Leider sind Optimierungen beim ansprechen über System.gc() eher ungesehen helfen mir aber hier schon etwas.
Mit dem Aufruf nach einem Durchlauf eines Paares kommen gleich 20 MB wieder frei.

Gibt es noch weitere Mittel und Wege um per Code Optimierungen durchzuführen?

Martin
Es gibt keine if Schleife -> http://www.if-schleife.de/
Ansonsten GPL/GNU/Linux/Debian/Free Software 4 Ever :D

Benutzeravatar
bmario
Beiträge: 1257
Registriert: 05.09.2007 12:15:47
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Dresden

Re: [Java]GC Optimierungen

Beitrag von bmario » 09.06.2010 15:11:08

Du könntest ja "einfach" versuchen Speicherplatz zu sparen mit z.B. static Variablen*
Oder die rekursive Lösung so umschrieben, dass z.B. nur eine Liste alle Verzeichnisse, die du bearbeiten willst zunächst rekursiv aufgebaut wird.
Und diese Liste danach Iterativ abgehen.

Ich behaupte mal, wenn du ein Speicherproblem hast, ist eher dein Algorithmus überarbeitungswürdig, als die Müllsammlung :)

*ich hoffe die gibt es überhaupt in Java, ich kenne C/C++ da besser.

Mario
Nichts zu tun ist viel besser,
als mit viel Mühe nichts zu schaffen. - Laotse

paedubucher
Beiträge: 939
Registriert: 22.02.2009 16:19:02
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Schweiz
Kontaktdaten:

Re: [Java]GC Optimierungen

Beitrag von paedubucher » 13.06.2010 13:49:54

Der Aufruf von System.gc(); ist, soviel ich weiss, nicht deterministisch. D.h., du kannst nicht sicher sein, ob der Garbace-Collector auch wirklich aufgerufen wird. Ich hatte in Java schon einmal ein ganz übles Problem. Damals wollte ich Dateien löschen, auf die zwar keine gültigen File-Referenzen mehr bestanden, die File-Objekte auf die Dateien jedoch noch im Speicher existiert haben. Damals war die "Lösung" auch, einfach vor jedem Löschen noch einmal System.gc() aufzurufen. 8O Das hat zwar in meinem Fall immer funktioniert, eine 100%-ige Garantie, ob es auch immer funktioniert, würde ich aber nicht abgeben.

Zitat aus der Javadoc:
Sun Microsystems hat geschrieben:Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.
:hail: Bitte, bitte, oh JVM
:hail: Rufe den Garbage-Collector auf

Ich habe schon mal eine Art "ls -r" in Java nachgebaut. Sobald ich das dann auf dem Root-Verzeichnis bzw. auf "C:\" aufgerufen habe, bekam ich eine OutOfMemory-Exception. Mich würde es auch interessieren, wie man das ohne System.gc() anständig optimieren kann.
Habe nun, ach! Java
Python und C-Sharp,
Und leider auch Visual Basic!
Durchaus programmiert mit heissem Bemühn.
Da steh' ich nun, ich armer Tor!
Und bin so klug als wie zuvor.

Benutzeravatar
shoening
Beiträge: 914
Registriert: 28.01.2005 21:05:59
Lizenz eigener Beiträge: MIT Lizenz

Re: [Java]GC Optimierungen

Beitrag von shoening » 13.06.2010 18:16:15

Hi,

zunaechstmal hat paedubucher natuerlich recht. Den GC kann man vom Programm aus selten beeinflussen.

Aber wie bei jeder Optimierung solltest Du wissen, wo Du hin willst bzw. wann Du fertig bist.
Um Speicherplatz zu sparen kannst Du der JVM einfach weniger Speicher geben (-Xmx). Wenn die JVM dann
wieder Speicher braucht, wird sie den GC automatisch anwerfen.

Den Tip von bmario kann ich nur in Frage stellen. Static Variable in dem Scenario fuehren eher zu Speicherloechern.

Ciao
Stefan
Bürokratie kann man nur durch ihre Anwendung bekämpfen.

michaels
Beiträge: 1164
Registriert: 29.03.2009 18:12:25

Re: [Java]GC Optimierungen

Beitrag von michaels » 13.06.2010 19:13:27

shoening hat geschrieben:Um Speicherplatz zu sparen kannst Du der JVM einfach weniger Speicher geben (-Xmx). Wenn die JVM dann
wieder Speicher braucht, wird sie den GC automatisch anwerfen.
Naja, deine Theorie hat allerdings den Haken, dass das Programm so auch schneller in einen OutOfMemory Fehler laufen kann...und dann war es das.

Eine schöne Lösung für das Problem habe ich allerdings auch nicht. Es soll sich aber einiges an den FileSystem Zugriffen mit dem JDK 7 ändern (besonders was rekursives durchlaufen angeht - dafür gibt es dann sogar eine spezielle Methode (walkFileTree)).

Benutzeravatar
shoening
Beiträge: 914
Registriert: 28.01.2005 21:05:59
Lizenz eigener Beiträge: MIT Lizenz

Re: [Java]GC Optimierungen

Beitrag von shoening » 13.06.2010 19:53:13

Hi,

das mit dem OutOfMemory waere allerdings gut. Wenn man das leicht erzielen kann, kann man das Programm
auch gut durchmessen und die Stellen im Programm, die besonders verschwenderisch mit Speicher umgehen, identifizieren.

Dafuer kann man erst mal mit jmap einen Heap-Dump erzeugen und dann weiterschauen.

Viele Probleme lassen sich aber auch im Vorfeld schon durch Verwendung geeigneter Design Pattern (bzgl. Oeffnen und Schliessen
von Resourcen denke ich da an ein Code-Template, das sicherstellt, das die Dateien wieder geschlossen werden) vermeiden.

Andererseits leisten Werkzeuge wie checkstyle und findbugs immer gute Dienste.

Ciao
Stefan
Bürokratie kann man nur durch ihre Anwendung bekämpfen.

Milbret
Beiträge: 827
Registriert: 26.05.2008 12:04:54
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Nörten-Hardenberg
Kontaktdaten:

Re: [Java]GC Optimierungen

Beitrag von Milbret » 13.06.2010 19:56:22

Danke für die Rückmeldungen.
Hatte den Thread über die Tage etwas vergessen.
Trotzdem werde ich noch Optimierungen vornehmen.
An den ein oder anderen Stellen gibt es locker Möglichkeiten :)

Ich werde dafür aber noch einige Tests machen müssen damit die Änderungen nicht mehr Probleme machen als sie lösen sollen.
Ich habe mit einigen extra Parameter an java bereits ordentlich Speicher sparen können.

Aktuell mache ich aber noch den Fehler, dass ich viele Objekte nicht auf null setze, sobald diese nicht mehr benötigt werden.
Vor allem auch beim loggen lasse ich immer wieder ein FileOutputStream anlegen, was ebenfalls immer wieder Spicher schluckt.
Dies sind Dinge die ich aber nicht kannte zum beginn der Entwicklung.
Nun bin ich aber schlauerer und werde diese Probleme lösen.

Martin
Es gibt keine if Schleife -> http://www.if-schleife.de/
Ansonsten GPL/GNU/Linux/Debian/Free Software 4 Ever :D

Benutzeravatar
bmario
Beiträge: 1257
Registriert: 05.09.2007 12:15:47
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Dresden

Re: [Java]GC Optimierungen

Beitrag von bmario » 09.07.2010 13:16:30

Nachdem ich für die Uni ein letzter Zeit ein paar Algorithmen über Graphen schreiben musste, ist mir noch eine weitere Möglichkeit eingefallen.

Du benutzt einfach keine Rekursion ;)

Ich drücke mal den Algorithmus etwas Pseudomäßig aus:

Code: Alles auswählen

folders = [ "/" ];

while (not is_empty(folders)) {
  foreach(folder in folders) {
    temp = [ ];
    foreach(file in folder) {
      if is_folder(file) {
        temp.add(file);
      }
      else {
        do_something_with_file(file);
      }
    }
  }
  folders = temp;
}
Ich weiß, ein wenig spät.. :)
Nichts zu tun ist viel besser,
als mit viel Mühe nichts zu schaffen. - Laotse

Milbret
Beiträge: 827
Registriert: 26.05.2008 12:04:54
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Nörten-Hardenberg
Kontaktdaten:

Re: [Java]GC Optimierungen

Beitrag von Milbret » 09.07.2010 18:58:46

Oh danke :)
Hab den Thread gerade per Google gefunden als ich per Java GC gesucht hab.
Ich werde mal deinen Vorschlag nutzen.
Dies kann aber unter Umständen und schlechter Programmierung meinerseits mehr Speicher kosten :(

Aktuell habe ich eine Optimierung gemacht die wohl hilft.
Da ich die Dateinamen im aktuellen Ordner in einer ArrayList speichere, habe ich diese nun per Hand auf null gesetzt wenn ich diese nicht mehr brauche.
Ebenfalls habe ich meinen Homeserver nun von USB auf eSata umgestellt da dies etwas langsam war :)
Nach ein paar Tests werde ich mehr berichten können.
Aber der letzte Vorschläge wäre interessant.

Martin
Es gibt keine if Schleife -> http://www.if-schleife.de/
Ansonsten GPL/GNU/Linux/Debian/Free Software 4 Ever :D

Benutzeravatar
ruwen
Beiträge: 389
Registriert: 06.04.2003 18:37:25

Re: [Java]GC Optimierungen

Beitrag von ruwen » 10.07.2010 12:06:14

Milbret hat geschrieben:Da der Speicher durch kurzlebige Objekte wie die Strings der absoluten Dateipfaden sowie mit Threads ordentlich verschlungen wird, wollte ich mal wissen ob es dafür einen guten GC gibt.
Gegebenenfalls (weiß nicht wie genau dein PGM aussieht) kann dir da die Methode String#intern() weiterhelfen: http://download.oracle.com/docs/cd/E174 ... tml#intern()

Ansonsten kann du mit Threadpools das Probleme mit dem erzeugen neuer Threads (und dem dazugehörigen einsammeln der Leichen durch den GC) vermeiden.

Milbret
Beiträge: 827
Registriert: 26.05.2008 12:04:54
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Nörten-Hardenberg
Kontaktdaten:

Re: [Java]GC Optimierungen

Beitrag von Milbret » 14.07.2010 17:16:04

Hallo,
da ich heute mal wegen der Hitze etwas früher Feierabend gemacht habe, hab ich mal mit den GC Einstellungen per java gespielt.
Mit der Option -Xincgc kam bisher das beste Ergebnis raus.
Bei 10 Threads und 10 MB Schreib/Lese Puffer pro Thread kommt er nicht über 190mb.
Bisher war er mit anderen GCs und dem Default um die 200 bis sogar an den 1 GB Ram.

Dies ist ein erfreuliches Ergebnis auch wenn ich eher erfreut wäre wenn der Default GC schon ein solches Ergebnis bringen könnte.
Aber um sicher zu gehen, dass ich endlich den richtigen GC für das Programm gefunden habe werde ich den Durchlauf nach einer Sicherung wiederholen.
Dann darf der GC seine Muskeln spielen lassen.

Trotzdem werde ich noch eine paar Anpassungen machen um möglichst viel Speicher frei zu bekommen.

Nachtrag:
Es war nicht -Xingc sondern XX:+UseParallelGC und XX:+UseAdaptiveSizePolicy die den Speicher ordentlich runter hauen.
Sollte mal das Skript für den Aufruf wieder aufräumen.

Martin
Es gibt keine if Schleife -> http://www.if-schleife.de/
Ansonsten GPL/GNU/Linux/Debian/Free Software 4 Ever :D

Antworten