2017-01-25 4 views
3

平均データ長が15バイトの160万バイト以上のデータに2.3GB相当のデータが含まれているかなり大きなデータセットがあります。各バイト[]キーの値はint型であるため、ハッシュマップの半分近く(6GBを超える)のメモリ使用量は、各バイト配列の16バイトのオーバーヘッドから構成されます。すべてのキーのシングルバイト[]配列を持つJavaハッシュマップ

オーバーヘッド= 8バイトヘッダー+ 4バイトVMによって16バイトに切り上げられた長さ。

私のオーバーヘッドは2.5GBです。

可変長のバイト[]キーを1つの大きなバイト配列に格納するハッシュマップの実装を知っている人はいないでしょうか?(1バイトの長さのフィールドを除いて)オーバーヘッドはありませんか?

私は使用しているプレーンなTrove TObjectIntHashMapと比較して、通常はパフォーマンスのオーバーヘッドがあり、CPU使用率はメモリ使用量よりも高くなっているため、インメモリDBは使用しません。 128ギガバイト以上、そこに簿記のオーバーヘッドの程度であることと、実際の問題がある - 事前ほとんどのパソコン以来

+0

配列が(等号を実装)またはhashCode()メソッドはありません、あなたトローブのハッシュマップはあなたのためにこれらを提供していますか? –

+0

ハッシュマップの_key_として 'byte []'を使っているのはなぜですか? –

+0

どのJVMを使用していますか?私の印象は)それは私が等号を(上書き全体の構造は8 –

答えて

2

おかげで16ギガバイト、これらの日、多くの場合、サーバ32がありますか?

バイトデータを1つの大きな配列に連結した場合 - 大きな配列のスライスを参照するために、個々の値がどのように見えるかについて考える必要があります。

最も一般的には、あなたが開始すると:ポインタ(?おそらくわずか4バイト)の

public class ByteSlice { 
    protected byte[] array; 
    protected int offset; 
    protected int len; 
} 

しかし、それはだ8バイト+サイズ+ JVMのオブジェクトヘッダ(64ビットJVM上の12のバイト)。だからおそらく合計24バイト。

私たちがこの単一目的を最小限にしようとするならば、まだオフセットのために4バイトが必要になります。

public class DedicatedByteSlice { 
    protected int offset; 
    protected byte len; 

    protected static byte[] getArray() {/*somebody else knows about the array*/} 
} 

これはまだ5バイト(おそらく8まで)+ JVMオブジェクトヘッダーです。おそらくまだ合計20バイトです。

オフセットの逆参照のコストとそのオブジェクトを追跡するコストは、小さな配列を直接格納するコストよりも実質的に低いとは思われません。

一つの更なる理論的可能性 - それはオブジェクト構造化代入を考えることが可能である

ではないので、マップキーを構造化代入それがされなくなったデータように「長さ&オフセットません」オブジェクト。次に、(長さ、オフセットなどの)スカラーパラメータのセットとして渡され、ハッシュマップ実装では、個別のコンポーネントの配列(たとえば、単一のObject [] keyArrayではなく)に格納されます。

しかし、私はあなたの(特に)ユースケースに既存のハッシュマップ実装を提供するライブラリはほとんどないと思います。

の値がの場合、Javaは複数の戻り値またはメソッドOUTパラメータを提供しないため、おそらく無意味です。それは、オブジェクトに非構造化データを「ボクシング」することなく、通信を非実用的にする。ここではマップキーについて具体的に質問していますが、これらはパラメータとして渡されますが返される必要はありません。そのようなアプローチは理論的に検討することができます。

[拡張] さえ与えられ、このことはトリッキーになり - 地図APIおそらくあなたのユースケースのための人口は(、LENオフセット)キーを定義することでなければならないとして、検索対人口のための非対称になることがあります。実用的なルックアップはまだ具体的なbyte []配列によって可能性があります。

OTOH:かなり古いラップトップでさえ16GBになりました。そして、これを書く時間(維持する時間4〜10)は、余分なRAMの小さなコストよりもはるかに価値があるはずです。

+0

ええ、私は()オフセット、バイトLENをint型の単純なGETを考えていたされているので、バイトを使用しています問題は、あなたがしなければならない固定長「バケット」に、配列を分割するために頼ることなく、すべてのキーのための単一の大規模なバイト[]配列内のオフセットにバイト[]キーを翻訳からのオフセットを見つけるだろうか、ハッシュ関数であります平均キーサイズは最大鍵長その後、はるかに少ないだろうとして、その後多くのスペースを無駄に最大のキーと同じ大きさ。私は32ギガバイトのRAMを持っていますが、私は説明するために、かなりの(処理中に、他のデータのためにそれの残りの部分を使用しています)、従ってI n私の記憶の使い方で控えめになることを願っています。 – daedalus

+0

マップのvsルックアップを設定するための非対称APIに対処するために私の答えに追加されました。あなたが私の答えに価値を見出すように思われるので、/ upvoteを受け入れてください。 –

関連する問題