5

大量のデータをメモリに保持する必要のある「ビッグデータ」ソフトウェアを書いています。私はc++でプロトタイプを作成しました。ただし、実際のエンドユーザーは通常Javaでコーディングするため、Javaプロトタイプも作成するように求められました。

私は、Javaのメモリフットプリントといくつかの予備テストのバックグラウンド読み取りを行いました。たとえば、私がこのオブジェクトを持っているとしましょう

public class DataPoint{

    int cents, time, product_id, store_id;

    public DataPoint(int cents, int time, int product_id, int store_id){
    this.cents = cents;
    this.time = time;
    this.product_id = product_id;
    this.store_id = store_id;
    }
}

C ++では、この構造のサイズは16バイトであり、これは理にかなっています。Javaでは、間接的である必要があります。たとえば、これらのオブジェクトを10m作成し、Runtime.totalMemory()-Runtime.freeMemory()を前後に使用してから、必要に応じて分割すると、構造ごとに約36バイトが取得されます。〜2.4xのメモリの違いはかなり厄介です。何億ものDataPointをメモリに保持しようとすると、醜くなります。

私はどこかで、Javaでこのような場合、データを配列として格納する方がよいことを読みました。基本的には、行ベースのストアではなく、列ベースのストアです。私はこれを理解していると思います。列ベースの方法は参照の数を減らし、おそらくJVMはintを8バイトの単語にインテリジェントにパックすることさえできます。

1つの非常に大きな次元(数百万/数十億のデータポイント)と1つの非常に小さな次元(O(1)の列/変数)を持つ本質的にメモリブロックであるメモリフットプリントを削減するために、他にどのようなトリックを使用できますか?

エントリごとに正確に16バイトを使用する4つのint配列としてデータを格納することが判明しました。レッスン:小さなオブジェクトは、Javaでは厄介な比例オーバーヘッドがあります。

4

3 に答える 3

2

データ構造がJavaでどれだけのメモリを使用するかを確認するのはそれほど簡単ではありません。totalMemory()は、実際の使用量よりも大きいvmに割り当てられたスペースを示します。データ構造のスペース消費を示すJavaプロファイラーを使用してみることができます。セットアップと実行は非常に簡単です。便利な無料ツールの1つは、Java独自のVisualVMです。これは、たとえば、アプリケーションのメモリ動作を示します。また、JavaのGCを使用した場合の動作についても少し学びます。

パフォーマンスフットプリントを示すVisualVMスクリーンショット(http://visualvm.java.net/features.htmlからの画像): ここに画像の説明を入力してください

可能であれば、変数を最終的にすることも検討する必要があります。これにより、Java VMはコードを少しだけ最適化できます(ただし、スペースを節約できるかどうかはわかりません)。

于 2012-12-31T16:42:46.123 に答える
0

まず、オブジェクトは、では不可能な実行可能型情報などをカプセル化するため、のオブジェクトJavaは常にバージョンよりもわずかに大きくなります。さらに、手動で行う必要のあるメモリ管理が容易になるため、コードのこの部分をコードベースの一部ではないと見なすこともできます。 C++instanceofC++C++

Flyweight Patternを調べてメモリ要件を減らし、を再利用することができますDataPoints(クラスをImmutableにします)。あなたが言うようにあなたが何十億ものポイントを持っているなら、いくつかはおそらく同じ値になるだろうと私は思います。
ここにいる他の人たちが、メモリ空間での最適化に関するより具体的な情報を提供すると確信しています。

于 2012-12-31T16:42:49.650 に答える
0

値の範囲によっては、より小さなデータ型を使用できる場合があります。一部のメンバーにバイトまたはショートを使用することをやめることができますか?

于 2012-12-31T16:50:52.877 に答える