Javaの配列サイズ

Javaのオブジェクトのサイズは、Habreで既に説明されています(たとえばhereまたはhere) 。 多次元配列のサイズについて詳しく説明したいと思います。これは私にとっては予想外の単純なことです。



メモリから計算アルゴリズムを最適化する際、特定の(非常に合理的な)入力パラメーターを使用すると、float [500] [14761] [2]の配列が作成されるという事実に出会いました。 (HotSpot 1.6.0_26 32ビットで、誰かが興味を持っている場合)メモリをどれくらい取ることができますか? 概算で、 500 * 14 761 * 2 * sizeof(float) = 500 * 14 761 * 2 * 4 = 59 044 000バイトと何らかのオーバーヘッドを推定しました。 実際にチェックすることにしたので、 Eclipse Memory Analyzerを使用しました(信じられないほど魔法のようなものをお勧めします!)。この配列の「保持ヒープ」は206 662 016バイトです。 良いオーバーヘッド-350%。 なぜそれが起こったのか見てみましょう。



私はインターネットでこの主題について書かれていることを検索し、英語で「 Java配列のメモリ使用量を計算する方法 」というかなり理解しやすい記事に出会いました。 簡単に言うと、プレゼンテーションの本質は次のとおりです。







この知識で十分です。 したがって、チェーンの最後にfloat [2]配列があります。 サイズは2フロート(各4バイト)+ 12バイトのオーバーヘッド-20バイトです。 8〜24バイトに揃えられます。 合計で、 500 * 14 761-7 380 500個のヒープでそのような配列を作成しました。 合計で、 177,132,000バイトの重量があります。



次に、float配列があります[14761] []-他の配列への14,761参照の配列。 このような各配列は、 14,761リンク(各4バイト)+ 12バイトのオーバーヘッド-59,056バイト(8で分割-位置合わせの必要なし)を占有します。 これらの配列は合計で500個あり、合計で29,528,000バイトの重量があります。



最後に、作成した実際の配列があります-float [500] [] []-2次元配列への500参照の配列。 500 * 4 + 12 = 2 012 、さらに4アライメントバイト-2 016バイトもかかります。



何が起こったのかを合計します: 177 132 000 + 29 528 000 + 2 016 = 206 662 016-メモリーアナライザーによって表示される数値のみ。



すぐに明らかな決定が浮かびました。配列の次元を昇順で並べることです。 float [2] [500] [14761]を作成しますが、アルゴリズムはこの問題を一切受けません。 この場合、どのサイズになりますか?





合計で59,060,056バイト、0.03%未満のオーバーヘッド、約150メガバイトのメモリが節約されました。



ここからは経験則に従います。測定による配列の次元が少なくとも事前にわかっている場合は、測定値を昇順に並べる必要があります。 また、メモリアナライザーを使用することも忘れないでください。プログラムについて多くを学ぶことができます。



All Articles