8

Java仮想マシンは、フィールドにもintサイズの幅を使用する場合がありshortます(これは内部実装によって異なります)。配列()のみが例外であり、内部的にshort[]も必要なスペースが少ないことが常に保証されています)。Dalvikint[]はどうですか?

たとえば、タイプが50のフィールドを含むクラスがありますshort。私のアプリケーションでは、これらのクラスが10000個存在することがあります。これは、shortフィールドが1MBのメモリを使用する必要があることを意味しますが Dalvikがshort内部で値に4バイトを使用する場合、これは2MBのメモリ使用量になります。

Dalvikが使用すると予想されるメモリの量はどれくらいですか?(これは内部メモリの使用を指します。たとえば、Dalvikがすでにシステムからより多くのメモリを予約しているため、システムのメモリ使用量に反映されない可能性があることを認識しています。)

4

2 に答える 2

4

dalvikでは、doubleフィールドとlongフィールドは8バイトであり、その他すべて(shortを含む)は4バイトです。

一方、短い配列は、要素ごとに2バイトを必要とします(配列とオブジェクトの簿記のための先行スペースに加えて)。

配列

new-arrayオペコードはスペースを割り当てるために呼び出します(dvmAllocArrayByClass71行目)。次に、これは呼び出しますdvmAllocPrimitiveArray(行113)。のスイッチでdvmAllocPrimitiveArrayは、「S」の場合が短い配列に使用されます。allocArraywidth = 2で呼び出していることがわかります(38行目)。

allocArrayで、配列のサイズサイズを計算するために次の計算を実行します。

size_t elementShift = sizeof(size_t) * CHAR_BIT - 1 - CLZ(elemWidth);
size_t elementSize = length << elementShift;
size_t headerSize = OFFSETOF_MEMBER(ArrayObject, contents);
size_t totalSize = elementSize + headerSize;

簡単に言うと、32ビットシステムでは、この計算は次のようになります。

size_t elementShift = (4 * 8) - 1 - 30; //== 1;
size_t elementSize = length << 1; //i.e. length * 2
size_t headerSize = <some constant value>;
size_t totalSize = length*2 + <some constant value>;

短い配列は要素ごとに2バイトかかります。

田畑

new-instanceオペコードは(181行目)を呼び出して、dvmAllocObject新しいオブジェクトにスペースを割り当てます。objectSize割り当てられるサイズは、のフィールドに基づいていますClassObjectobjectSizeに設定されていcomputeFieldOffsetsます(行3543)。この関数でfieldOffsetがインクリメントされるすべてのインスタンスを見つけると、常に4バイト単位でインクリメントされていることがわかります。

短いフィールドは4バイトかかります。

于 2012-10-26T04:02:25.947 に答える
2

(コメントになりますが、長すぎます。)

JVMは概念的には4バイトのレジスタを備えたマシンであり、スタックフレーム内の他のすべてのガベージを使用しても大きな違いはないため、4バイトのフィールドを「短い」ローカル変数に使用することはかなり日常的です。

たとえば、フィールドでは、ストレージの節約と、拡張と調整にサイクルを費やす必要があるというトレードオフに依存する可能性があります。拡張には、多くの場合、わずかなサイクルがかかります。境界の調整に関して「不可知論的」と思われるアーキテクチャでも、通常はペナルティがあります。境界外アクセスの場合、ワード/ダブルワード境界を維持するために最初にフィールドを再配置せずにフィールドを「パック」すると、パフォーマンスが低下する可能性があります。

したがって、JVMが「パック」することを選択した場合、通常、フィールドの再配置が必要になります。ナイーブなJVMは、JVMのいくつかの側面を単純化するため、再配置を回避しますが、(一例として)AS / 400では、インスタンスフィールドを積極的に並べ替えてパックすると、ストレージを大量に消費するアプリのパフォーマンスが30%向上することがわかりました。

Dalvikの内部を見たことがありません。標準のSunから派生したJVMは、歴史的に(最近は何も調べていませんが)、.classファイル内のもののレイアウト/順序に依存していたため、「自然に」並べ替えに適していませんでした。ただし、Dalvikは.classファイルを再構成するため、インスタンスフィールドの並べ替えを行うのに適しています。

Dalvikshortがフィールドをパックするという仮説をテストするには、数十のインスタンスフィールドを連続して使用するクラスを作成し、結果のオブジェクトサイズを決定する必要があることに注意してください。また(最初のケースでパッキングが見られると仮定して)、フィールドがインターリーブされたクラスを作成し、shortDalvikがパッキングを達成するためにそれらを並べ替えるかどうかを確認しますintlong

于 2012-10-25T19:38:19.463 に答える