大量のデータをメモリに保持する必要のある「ビッグデータ」ソフトウェアを書いています。私は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では厄介な比例オーバーヘッドがあります。