Wir hatten bisher Erfolg ChronicleMap
für die meisten Dinge, die wir verwenden wollten, und die meisten Datensätze haben gut funktioniert. Ein Anwendungsfall, den wir verwenden, verwendet es als Multimap und deckt damit die meisten Bedenken ab. Wir verwenden es speziell in diesem Fall als Map<String,Set<Integer>>
. Wir sind jedoch auf einige interessante JVM-Abstürze gestoßen und haben Probleme, ein deterministisches Muster zu finden, um sie zu vermeiden.ChronicleMap verursacht JVM zum Absturz, wenn die Werte in Größe sehr variabel sind
Also, bevor wir alle Set<Integer>
in ChronicleMap
setzen, haben wir es vollständig in der JVM, also schreiben wir sofort, um die Fragmentierung zu reduzieren. Da wir es vollständig im Speicher haben, können wir bestimmen, was die maximale und durchschnittliche Größe Set<Integer>
ist, und können die ChronicleMap
mit ChronicleMapBuilder.averageValueSize
geeignet Größe. In den meisten Fällen funktioniert das gut.
In einigen Fällen jedoch stürzt die JVM ab, wenn die Größe der Set<Integer>
weit vom Durchschnitt abweicht. Zum Beispiel könnte die durchschnittliche Größe 400 betragen, aber wir könnten Ausreißer-Sets mit 20.000 ganzen Zahlen haben. Wir können die Karte immer noch mit der durchschnittlichen serialisierten Größe eines Satzes von 400 ganzen Zahlen sortieren, und sie fängt an, ChronicleMap
in Ordnung zu füllen, bis sie eine sehr große Liste erreicht.
Also die Frage ist: Wie finde ich heraus, wie groß ich vom Durchschnitt abweichen kann? Ich hatte gehofft, dass der Durchschnitt in der Tat ein Durchschnitt war, aber es scheint einige Max zu geben, die dazu führen, dass die JVM stirbt.
Wir entwickelten einen Algorithmus, um die großen Sätze in kleinere Sätze aufzuteilen (z. B. wenn der Schlüssel AAA war, dann gibt es jetzt Schlüssel AAA: 1, AAA: 2, ... AAA: n). Die Größe des Split-Sets war 10-mal so groß wie die Durchschnittsgröße. Mit anderen Worten, wenn die Durchschnittsgröße 500 war, aber wir hatten eine Menge von 20.000, teilten wir sie in vier 5.000 (500 * 10) Elementmengen auf.
Dies funktionierte in den meisten Fällen, aber dann stießen wir auf einen weiteren merkwürdigen Fall und selbst diese Aufteilung war nicht ausreichend. Ich habe den Faktor auf das 5-fache der Durchschnittsgröße reduziert und jetzt funktioniert es wieder ... aber woher weiß ich, dass das klein genug ist? Ich denke, das Quellproblem zu wissen oder genau zu bestimmen, was es verursacht, ist der beste Weg, aber leider habe ich keine Ahnung, warum ChronicleMap
hier kämpft.
Auch, FWIW, ich benutze eine ältere Version 2.1.17. Wenn dies ein Fehler ist, der in einer neueren Version behoben wurde, würde ich gerne ein kleines Detail über den Fehler wissen und wenn wir es mit unseren eigenen Mitteln vermeiden könnten (wie das Teilen der Sets), aber weiterhin 2.1.17 benutzen (wir werde später aufrüsten, will das Boot nicht zu sehr rocken.
Es ist ein wenig unklar, wie Sie chunkSize in Ihrem Beispiel berechnet haben. Nehmen wir an, unser Durchschnitt ist 500 Ints, also bei 4 Bytes pro Int plus einem kleinen Schlüssel könnten wir pro Eintrag ~ 2048 Bytes erhalten.Hast du das durch 8 geteilt (konservativer als 4), um die 256 chunkSize in deinem Beispiel zu erhalten? Wenn dem so ist, scheint es mathematisch zu sein, dass die maximale Listengröße ungefähr achtmal so groß ist wie die durchschnittliche Listengröße (nachdem ich meine rostige Algebra verwendet habe). – Depressio
@Depressio Ich nehme an, dass in Ihrem Fall die durchschnittliche Eintragsgröße 2048 nicht überschreitet. Wenn es> 2048 ist, wird 256 aus der Größe/8, Größe/4 Fenster, und die Größe der Blöcke wird standardmäßig 512. Um sicher zu sein, können Sie Konfigurieren Sie die Chunk-Größe einfach über 'ChronicleMapBuilder.actualChunkSize()'. Je kleiner die Chunk-Größe ist, desto kleiner ist die durchschnittliche interne Fragmentierung (Speicherverschwendung für die Ausrichtung auf die nächste Chunk-Grenze). – leventov
OK, also je kleiner die Chunk-Größe, desto weniger Fragmentierung, aber der kleinere Maximalwert, den ich speichern kann, bevor die JVM abstürzt ... aber eine größere Chunk-Größe bedeutet mehr Fragmentierung, aber die Listen können größer sein? Knifflig, knifflig. Und um es klar zu sagen, die durchschnittliche Wertgröße wird auf jeden Fall 2048 überschreiten, abhängig vom Datensatz. Wenn ich die Größe des MAX-Wertes kenne, könnte ich chunkSize auf maxValueSize/64 setzen? – Depressio