0

しばらく前に、ChronicleMap が として使用されていることについて、この質問Map<String,Set<Integer>>をしました。基本的に、平均Set<Integer>が 400 のコレクションがありますが、最大長は 20,000 です。ChronicleMap 2 では、これにより悪質な JVM クラッシュが発生していました。ChronicleMap 3.9.1 に移行したところ、例外が発生し始めました (少なくとも JVM クラッシュではありません)。

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)

これは、平均値よりもはるかに外れている値を持っているためだと思います。ビルダーに与えた平均値に基づいて ChronicleMap が最大チャンク数を 6328 と判断したと思いますが、23045 チャンクを必要とする巨大な値があるとは予想していませんでした。

だから私の質問は、これを解決するための最良の方法は何ですか? 私が検討しているいくつかのアプローチですが、まだ確信が持てません:

  1. ChronicleMapBuilder.maxChunksPerEntryまたはを使用しChronicleMapBuilder.actualChunkSizeます。とはいえ、それらを何に設定する必要があるかを決定論的に把握するにはどうすればよいですか? また、設定が高すぎると、断片化が多くなり、パフォーマンスが低下する可能性がありますよね?
  2. 「最大コレクション サイズ」を設定し、非常に大きなコレクションを多くの小さなコレクションに分割し、それに応じてキーを設定します。たとえば、私のキーがサイズ 10000 のXYZを生成する場合、おそらくそれをサイズ 2000 のセットを持つ5 つのキー、などSet<Integer>に分割できます。その結果、不要なコードが大量に作成されます。他の質問にも同じ計画がありました。XYZ:1XYZ:2

他の考え/アイデアは大歓迎です!

4

1 に答える 1

1

手動で指定しない場合maxChunksPerEntry()、エントリの最大サイズはセグメント層のサイズ (チャンク単位) で制限されます。したがって、必要なのは、セグメント層のサイズを大きくすることです。actualSegments(1)JVM 内の複数のスレッドからマップに同時にアクセスしない場合は、最初に を構成することを試みることができます。ChronicleMapBuilder.actualChunkSize()actualChunksPerSegmentTier()および を使用して、これらの構成をさらに制御できますentriesPerSegment()

デフォルトでは、ChronicleMapBuilder は構成された平均値サイズの 1/8 から 1/4 の間のチャンク サイズを選択します。したがって、セグメント層のサイズが 6328 チャンクの場合、セグメントは約 1000 エントリを含むように構成されます。平均値セットのサイズが 400 要素で、最大値が 20,000 の場合、平均値と最大値の差は約 50 倍になるはずですが、スタック トレースから、エントリの 1 つが平均の 2000 倍を優に超えているように見えます。おそらくあなたは何かを説明していません。

また、このような大きな値については、メモリ効率の良い値シリアライザーを開発して使用することをお勧めします。これは、デフォルトの値シリアライザーが大量のガベージを生成するためです。例)fastutil または Koloboke または Koloboke Compile ライブラリからIntSet実装するプリミティブを使用できます。Set<Integer>

また、現在入手可能な最新バージョンを使用することをお勧めします。Chronicle Map 3.9.1 は既に古くなっています。

于 2016-12-14T20:21:45.997 に答える