0

これまでのところ、使いたいと思っていたことのほとんどに使用して成功してChronicleMapおり、ほとんどのデータセットは問題なく機能しています。私たちが持っているユースケースの 1 つは、それをマルチマップとして使用することで、そうすることでほとんどの問題をカバーします。Map<String,Set<Integer>>この場合は特にとして使用しています。ただし、いくつかの興味深い JVM クラッシュが発生しており、決定論的なパターンを見つけるのに苦労しているため、それらを回避できます。

したがって、すべてを に入れる前に、Set<Integer>全体ChronicleMapを JVM に持っているので、断片化を減らすために一度に書き込みます。完全にメモリ内にあるため、最大サイズと平均サイズを判断でき、を使用して適切なSet<Integer>サイズを簡単に設定できます。ほとんどの場合、これで問題なく動作します。ChronicleMapChronicleMapBuilder.averageValueSize

ただし、場合によっては、 のサイズがSet<Integer>平均から大きく外れると、JVM がクラッシュします。たとえば、平均サイズが 400 であっても、20,000 個の整数を含む外れ値セットが存在する可能性があります。400 個の整数のセットのシリアル化された平均サイズを使用してマップのサイズを変更することもできますChronicleMap。非常に大きなサイズのリストに到達するまで、問題なくデータが取り込まれ始めます。

問題は、平均からどれだけ逸脱できるかをどのように把握すればよいかということです。平均が実際に平均であることを望んでいましたが、それを超えるとJVMが停止する最大値があるようです。

大きなセットを小さなセットに分割するアルゴリズムを考案しました (たとえば、キーが AAA の場合、キーは AAA:1、AAA:2、... AAA:n になります)。分割セットのサイズは、平均サイズの 10 倍でした。つまり、平均サイズが 500 で、セットが 20,000 の場合、それを 4 つの 5,000 (500 * 10) 要素セットに分割します。

これはほとんどの場合うまくいきましたが、別の興味深いケースに遭遇し、この分割でさえ十分ではありませんでした。係数を平均サイズの 5 倍に減らしたところ、再び機能するようになりました...しかし、それが十分に小さいことをどのように確認できますか? ソースの問題を知ること、またはその原因を正確に特定する方法が最善の方法だと思いますが、残念ながら、なぜChronicleMapここで苦労しているのかわかりません。

また、FWIW、古いバージョンの 2.1.17 を使用しています。これが新しいバージョンで修正されたバグである場合、バグについて少し詳しく知りたいのですが、独自の手段 (セットを分割するなど) で回避できるかどうかを知りたいのですが、引き続き 2.1.17 を使用します (後でアップグレードします; ボートをあまり揺さぶりたくないだけです)。

4

1 に答える 1

1

バグを再現しないと 100% 確信は持てませんが、この場合に JVM クラッシュが発生する理由はわかります。私が正しければ、エントリ サイズが ChronicleMap の 64 * chunkSize を超えた場合に発生します。チャンク サイズは直接設定できますが、キーと値の平均サイズのみを設定すると、デフォルトで 2 の累乗、つまり averageEntrySize/8 と averageEntrySize/4 の間になります。ここで、平均エントリ サイズは averageKeySize と averageValueSize の合計です。に加えて、いくらかの内部オーバーヘッドが追加されます。したがって、あなたの場合、平均値-400または500 intのセット(各4バイト)+小さなキーがある場合、chunkSizeは256バイトとして計算されるため、エントリは256 * 64よりも小さくなるはずです= 16384 バイト。

繰り返しますが、このバグがどこから来たのかという仮説が正しければ、クロニクル マップ 3 にはこのバグはなく、平均サイズまたはチャンク サイズよりも任意に大きいエントリを許可する必要があります。

于 2016-05-27T12:29:48.627 に答える