Problem mit Garbage Collector
-
Hallo,
ich programmiere gerade eine Game-App für Android (mit Java und OpenGL). Die grafische Ausgabe mit OpenGL ES 2.0 funktioniert auch super. Zum Zeichnen einen Frames brauche ich durchschnittlich so 17ms (was absolut in Ordnung ist).Mein Problem ist jedoch, dass von Java im Hintergrund der Garbage Collector ausgeführt wird. So kommt es immer wieder mal vor, dass ein Frame bis zu 50ms braucht. Dies wiederum macht sich als Ruckeln in der grafischen Ausgabe bemerkbar.
Könnt ihr mir da weiterhelfen? Wie kann ich die Probleme mit dem GC in den Griff bekommen?
Vielen Dank für eure Hilfe,
LG arenas
-
Willkommen in der Java-Welt
-
Wie Mechanics es schon gesagt hat, willkommen in der Java Welt oder der Welt der Garbage Kollektoren. Einfach kommst du darum nicht herum. Das Problem kannst du in vielen Spielen beobachten, welche in Java oder z.B. C# entwickelt worden sind. Ein sehr typischer Kandidat als Beispiel ist Minecraft Java Edition. Da kannst du das sogar beobachten, wenn du F3 drückst und den verbrauchten Speicher anschaust. Und ein bekanntes Problem dort ist, dass die Leute Minecraft mehr Arbeitsspeicher zuordnen, wodurch mehr Speicher belegt wird, bevor er freigegeben wird, was zu starken Rucklern führt.
Es gibt grundsätzlich zwei Lösungen für das Problem. Das erste ist ein anderer Garbage Collector einzusetzen. Würde hier wahrscheinlich eine andere JRE bedeuten. Damit kenne ich mich allerdings nicht aus. Das dürfte auch allerlei anderer Probleme mit sich ziehen. Unity3D (C#) hat zum Beispiel für ihre Umgebung gerade angekündigt, dass sie ihren GC anpassen wollen: https://blogs.unity3d.com/2018/11/26/feature-preview-incremental-garbage-collection/
Die zweite Lösung ist per Software-Design dafür zu sorgen, dass du nicht ständig viele Objekte erstellst, welche wieder freigegeben werden müssen. Probiere Objekte langlebig hinzubekommen. Oder allenfalls auch mit Object-Pooling zu arbeiten. Das klingt jetzt einfach, ist es aber überhaupt nicht. Am besten setzt man das sehr gezielt ein und analysiert zuerst einmal, wo denn diesbezüglich Probleme vorhanden sind. Dazu gibt es entsprechende Memory-Profiler. JProfiler kommt mir da zum Beispiel in den Sinn, aber das kostet natürlich. Gibt wahrscheinlich noch andere Werkzeuge. Kenne mich diesbezüglich in Java nicht so gut aus.
-
Also, ich arbeite im Java Umfeld nur mit dem kostenlosen VisualVm und bisher hats immer gereicht. Allerdings haben mich in Java meist eher Memory Leaks und weniger die Performance interessiert.
Das zeigt aber schon in der Übersicht die CPU Auslastung und den Anteil des GC an, vielleicht kommst du damit schon weiter. Und es gibt im JDK das jstat Tool, damit kann man sich auch einige Infos ausgeben lassen, habe mich aber nicht im Detail damit beschäftigt.