A while back, I asked this question about a ChronicleMap being used as a Map<String,Set<Integer>>
. Basically, we have a collection where the average Set<Integer>
might be 400, but the max length is 20,000. With ChronicleMap 2, this was causing a rather vicious JVM crash. I moved to ChronicleMap 3.9.1 and have begun to get an exception now (at least it's not a JVM crash):
java.lang.IllegalArgumentException: Entry is too large: requires 23045 chucks, 6328 is maximum.
at net.openhft.chronicle.map.impl.CompiledMapQueryContext.allocReturnCode(CompiledMapQueryContext.java:1760)
at net.openhft.chronicle.map.impl.CompiledMapQueryContext.allocReturnCodeGuarded(CompiledMapQueryContext.java:120)
at net.openhft.chronicle.map.impl.CompiledMapQueryContext.alloc(CompiledMapQueryContext.java:3006)
at net.openhft.chronicle.map.impl.CompiledMapQueryContext.initEntryAndKey(CompiledMapQueryContext.java:3436)
at net.openhft.chronicle.map.impl.CompiledMapQueryContext.putEntry(CompiledMapQueryContext.java:3891)
at net.openhft.chronicle.map.impl.CompiledMapQueryContext.doInsert(CompiledMapQueryContext.java:4080)
at net.openhft.chronicle.map.MapEntryOperations.insert(MapEntryOperations.java:156)
at net.openhft.chronicle.map.impl.CompiledMapQueryContext.insert(CompiledMapQueryContext.java:4051)
at net.openhft.chronicle.map.MapMethods.put(MapMethods.java:88)
at net.openhft.chronicle.map.VanillaChronicleMap.put(VanillaChronicleMap.java:552)
I suspect this is still because I have values that are far outliers to the mean. I assume ChronicleMap determined the maximum number of chunks to be 6328 based on the average value I gave the builder, but didn't expect there to be a gigantic value which needed 23045 chunks.
So my question is: what's the best way to go about solving this? Some approaches I'm considering, but still not sure on:
- Use
ChronicleMapBuilder.maxChunksPerEntry
orChronicleMapBuilder.actualChunkSize
. That said, how do I deterministically figure out what those should be set to? Also, this will probably lead to a lot of fragmentation and slower performance if it's set too high, right? - Have a "max collection size" and split the very large collections into many smaller ones, setting the key accordingly. For example, if my key is
XYZ
which yields aSet<Integer>
of size 10000, perhaps I could split that into 5 keysXYZ:1
,XYZ:2
, etc. each with a set of size 2000. This feels like a hack around something I could just configure in ChronicleMap though, and results in a lot of code that feels like it shouldn't be necessary. I had this same plan mentioned in my other question, too.
Other thoughts/ideas are appreciated!