ich meine eigenen Pass ein umgesetzt t etwas, das eine stabile Menge an Speicherbereinigung verursachen könnte. Der vollständige Code ist hier verfügbar: https://bitbucket.org/snippets/dimo414/argzK
Das Fleisch Diese beiden Verfahren sind, das Konstrukt und setzt eine große Anzahl von Objekten in einem bestimmten Zeitraum von Echtzeit (im Gegensatz Zeit oder CPU-Zeit-Gewinde):
/**
* Loops over a map of lists, adding and removing elements rapidly
* in order to cause GC, for runFor seconds, or until the thread is
* terminated.
*/
@Override
public void run() {
HashMap<String,ArrayList<String>> map = new HashMap<>();
long stop = System.currentTimeMillis() + 1000l * runFor;
while(runFor == 0 || System.currentTimeMillis() < stop) {
churn(map);
}
}
/**
* Three steps to churn the garbage collector:
* 1. Remove churn% of keys from the map
* 2. Remove churn% of strings from the lists in the map
* Fill lists back up to size
* 3. Fill map back up to size
* @param map
*/
protected void churn(Map<String,ArrayList<String>> map) {
removeKeys(map);
churnValues(map);
addKeys(map);
}
Die Klasse implementiert Runnable
, so dass Sie es (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 es die JVM nicht stoppt) und es für immer als 0
Sekunden als Konstruktorargument angeben.
habe ich einige Benchmarking dieser Klasse und fand es in der Nähe ein Drittel seiner Zeit (vermutlich auf GC) und identifiziert ungefähre optimale Werte von 15-25% Churn und einer Größe von ~ 500 blockiert ausgegeben. Jeder Lauf wurde 60 Sekunden lang ausgeführt, und die folgenden Graphiken zeigen die Thread-Zeit, wie sie von java.lang.managment.ThreadMXBean.getThreadCpuTime()
gemeldet wird, und die Gesamtzahl der Bytes, die vom Thread zugewiesen wurden, wie von com.sun.management.ThreadMXBean.getThreadAllocatedBytes()
berichtet. fast 100% seiner Zeit im Thread
Die Kontrolle (0% Churn) sollten im Wesentlichen alle GC nicht vorstellen, und wir können es kaum ordnet Objekte und verbringt sehen. 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, um jeden Zyklus zu schüren.
Dies zeichnet, wie die Gewinde Funktionen bei verschiedenen Zielgrößen für die Karte und Listen, wir hätten mehr Zeit als die Größe zunimmt sehen können, müssen in GC ausgegeben werden, und interessanterweise tatsächlich weniger Objekte Zuteilung wir am Ende, Da die Datenmenge größer ist, können im selben Zeitraum nicht so viele Schleifen erstellt werden. 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 Standardeinstellungen java
durchgeführt, daher kann das Spielen mit dem Heap unterschiedliches Verhalten verursachen - insbesondere ~ 2000 war die maximale Größe, die ich setzen konnte, bevor der Heap voll wurde bessere Ergebnisse bei einer größeren Größe, wenn wir die Größe des Heap erhöhen.
Danke, Stack-Überlauf braucht mehr von dir. –