Hallo ihrs,
ich bin im Rahmen meines Projektes auch auf ein Heap Problem gestossen.
Mein Projekt verarbeitet jede Menge Dateien und schickt die Daten an diverse Plugins.
Einige Plugins generieren ueberschaubare Objekte wie HashMaps.
Andere benutzen die hsqldb library um Daten in CACHED oder MEMORY Tables zu schreiben.
Nachdem alle Daten geparst wurden, werden die Daten der Plugins ausgewertet.
Bei denen die die DB benutzen bedeutet das eine Menge von SQL Statements.
Nun laeuft mein Tool soweit wunderbar fuer ein oder 2 Plugins bei gegebener Datenmenge.
Aber ich moechte auch sichergehen, dass es bei einer bestimmten groesseren Zahl an Dateien und
an Plugins auch ohne Heap Space Probleme laeuft.
Nun die Performance koennte ich ein wenig runterschrauben und setze eher auf CACHED Tables,
aber bei zig tausend Dateien und bei der Benutzung aller Plugins im extremsten Fall wuerde das wohl auch
den groessten Heap umhauen, unabhaengig davon ob der mit den Argumenten -Xmx gesetzt wurde oder auch nicht.
Jetzt hatte ich die Idee, ich koennte doch den benutzten Heap Space abfragen und wenn der ueber einen gewissen Prozentsatz geht,
dann warte ich solange bis irgendwie mehr HeapSpace frei geworden ist...
Das irgendwie bezieht sich hier im Moment auf den GarbageCollector.
Um das mal zu verdeutlichen habe ich in meinem Code die Zeile System.gc() hinzugefuegt, wohlwissend, dass der GC nicht umbedingt anspringt.
Der Code sieht wie folgt aus:
Java:
Timer timer = new Timer();
ShowWatingTimer swt = new ShowWatingTimer(progressState);
timer.schedule(swt, 100, 500);
while (progressState.isAskedForAborted())
;
timer.cancel();
// Die Run Methode der Klasse ShowWaitingTimer:
public void run()
{
//Cancel
if (usedTimes > 100)
{
state.setAborted(true);
state.setAskedForAborted(false);
System.out.println("Timeout!");
return;
}
// Clean up Heap Space
System.gc();
Runtime rt = Runtime.getRuntime();
long percentage = ((rt.totalMemory() - rt.freeMemory()) * 100)
/ rt.maxMemory();
// If heap space provides enough free memory continue with the process
if (percentage <= Config.MEMORY_FREE)
state.setAskedForAborted(false);
else if (usedTimes > 0)
System.out.print(".");
usedTimes++;
}
Die Ueberlegung ist halt, wenn Datenbanken und Plugins zu sehr beschaeftigt sind und gerade ne Menge Klassen hin und her schmeissen,
dann sollte das Tool halt warten, bis auch in der hsqldb zum Beispiel alle Transaktionen fertig sind und der GC dann eventuell abgelaufene Objekte loescht.
2. Ueberlegung ist noch, die Plugins, die die DB benutzen, erstellen am Anfang eine Verbindung zu ihrer DB. Macht es Sinn diese Verbindung aufrecht zu erhalten, bis
der gesamte Prozess abgelaufen ist oder sollte man eher fuer jedes Objekt, dass zu den Plugins geschickt wird eine Verbindung zur DB erstellen?
Immer eine Verbindung zu erstellen wuerde doch auch auf die Performance gehen oder?