Ich möchte herausfinden, wie etwas funktioniert, während es mit einer großen Menge an fortlaufender Speicherbereinigung konkurriert. Ich habe zuvor einen Benchmark-Test durchgeführt, wie es sich in einem stabilen Single-Thread-Lauf verhält, und ich möchte jetzt die gleichen Tests in einer stressgeladeneren JVM durchführen. im Wesentlichen würde ich gerne Hintergrundfäden haben, die Objekte in einem ziemlich konstanten Tempo erstellen und zerstören.
Ich suche nach Vorschlägen, wie man eine stabile, aber GC-intensive Operation implementieren kann. Es muss mehrere Ziele erreichen:
Java heap space
-Fehler GC overhead limit exceeded
Fehler Ich habe meinen eigenen Pass bei etwas implementiert, das eine stabile Menge an Garbage Collection verursachen könnte. Der vollständige Code ist hier verfügbar: Ссылка
Das Fleisch ist diese zwei Methoden, die eine große Anzahl von Objekten für einen bestimmten Zeitraum in Echtzeit erstellen und freigeben (im Gegensatz zu Thread-Zeit oder CPU-Zeit):
%Vor% Die Klasse implementiert Runnable
, sodass Sie sie (oder mehrere gleichzeitig) in einem eigenen Hintergrundthread starten können. Es wird so lange ausgeführt, wie Sie es angeben, oder wenn Sie es vorziehen, können Sie es als Daemon-Thread starten (damit die JVM nicht beendet wird) und es so angeben, dass es für immer mit 0
seconds als Konstruktorargument ausgeführt wird.
Ich habe ein Benchmarking dieser Klasse durchgeführt und festgestellt, dass es fast ein Drittel seiner Zeit damit verbracht hat, (vermutlich auf GC) zu blockieren und ungefähre optimale Werte von 15-25% Churn und eine Größe von ~ 500 zu identifizieren. Jeder Durchlauf wurde 60 Sekunden lang durchgeführt, und die folgenden Grafiken zeigen die Threadzeit, wie von java.lang.managment.ThreadMXBean.getThreadCpuTime()
und der Gesamtzahl der vom Thread zugewiesenen Bytes angezeigt, wie von com.sun.management.ThreadMXBean.getThreadAllocatedBytes()
gemeldet.
Das Steuerelement (0% Abwanderung) sollte im Wesentlichen keinen GC einführen, und wir können sehen, dass es fast keine Objekte zuordnet und fast 100% seiner Zeit im Thread verbringt. Von 5% bis zu 95% Abwanderung sehen wir ziemlich konstant etwa zwei Drittel der Zeit, die wir in Thread verbringen, vermutlich wird das andere Drittel in GC verbracht. Ein vernünftiger Prozentsatz, würde ich sagen. Interessanterweise sehen wir am sehr hohen Ende des Abwanderungsanteils mehr Zeit im Thread, vermutlich weil der GC so viel aufräumt, dass er tatsächlich effizienter sein kann. Es scheint ungefähr 20% ist eine gute Anzahl von Objekten in jedem Zyklus zu sein.
Hier wird dargestellt, wie der Thread bei verschiedenen Zielgrößen für die Karte und die Listen funktioniert. Wenn die Größe zunimmt, muss mehr Zeit in GC verbracht werden. Interessanterweise werden letztlich weniger Objekte zugewiesen, wie die größere Datengröße angibt Es ist nicht möglich, im gleichen Zeitraum so viele Schleifen zu erstellen. Da wir daran interessiert sind, die Menge an GC-Churn zu optimieren, mit der sich die JVM befassen muss, möchten wir, dass sie mit so vielen Objekten wie möglich umgehen und so wenig Zeit wie möglich im Arbeits-Thread verbringen muss. Es scheint also ungefähr 4-500 eine gute Zielgröße zu sein, da es eine große Anzahl von Objekten erzeugt und eine gewisse Zeit in GC verbringt.
Alle diese Tests wurden mit den standardmäßigen java
-Einstellungen durchgeführt, daher kann das Spielen mit dem Heap zu einem anderen Verhalten führen - insbesondere ~ 2000 war die maximale Größe, die ich einstellen konnte, bevor der Heap voll wurde noch bessere Ergebnisse bei einer größeren Größe, wenn wir die Größe des Heaps erhöhen.
Tags und Links java multithreading benchmarking garbage-collection