7

CおよびC++では、コンパイラーは構造体のデータメンバーを並べ替えることが許可されていないため、それらの並べ替え方法に注意しないと、スペースを浪費することになります。例えば:

struct S {
    int i;
    void *p;
    int i2;
};

int32ビットと64ビットのポインタを備えたプラットフォームではi、最初に配置され、次に32ビットのパディングが配置されるため、p64ビットに揃えることができます。i2次に、次の単語の半分を占め、その後にさらに32ビットのパディングが続きます。結果の構造体の長さは24バイトですが、p最初に宣言された場合、長さはわずか16バイトになります。配列にこれらの構造体が多数ある場合、メモリを節約し、キャッシュチャーンを減らすために、パディングを見つけて削除することが重要な最適化になることがあります。

Javaに同じ機能があるかどうか知りたいです。ボックス化されていないタイプ(intおよびなどboolean)は、参照と同じサイズかそれよりも小さいですか?そして、それらが小さい場合、コンパイラーは、後続のフィールドを整列させるためにパディングを挿入しないように、それらを並べ替えることができますか?最後に、もしそうなら、コンパイラはこれを行いますか?

現在、これについて特に最適化する必要はありません。Cの場合のように、フィールドを宣言する順序を選択するときに、これを念頭に置く必要があるかどうかを知りたいだけです。

4

4 に答える 4

4

Javaにはそのような問題があります。コンパイラは変数の宣言を処理し、プログラマはそれらをメモリ内のどこに割り当てるかを制御できません

于 2012-10-15T11:11:57.360 に答える
4

int型は常に 32 ビットであり、参照は通常、64 ビット JVM でも 32 ビットです。

欠点として、Java は各オブジェクトの先頭に 8 ~ 12 バイトのヘッダーを持ち、8 バイトのアラインメントを使用します。ところで、一部の C++ 環境では 16 バイトのアラインメントがあります。

ボックス化されていない型 (int や boolean など) は参照と同じサイズですか、それとも小さいですか?

boolean、byte、char、および short の場合は小さいと予想できますが、プリミティブは long と double の場合は参照よりも大きくなる可能性があります。

また、それらが小さい場合、後続のフィールドを揃えるためにパディングを挿入することを避けるために、コンパイラーはそれらを並べ替えることができますか?

JIT は、フィールドを再編成したり、最適化して取り除いたりすることさえできます。

最後に、もしそうなら、これを行うコンパイラはありますか?

コンパイルはjavacほとんど最適化を行わず、バイトコードを見ても、実行時に何が起こるかについてほとんど手がかりが得られません。JIT は、選択した方法でオブジェクトのフィールドを最適化できます。

Cで行うように、フィールドを宣言する順序を選択するときに、これを念頭に置く必要があるかどうかを知りたいだけです.

私見、Cで使用した可能性のあるほぼすべての最適化トリックは、もはやJavaには適用されないと想定できます。そうする少数のうち、それらはまったく同じではないかもしれません。

JIT が必要に応じてコードを最適化し、プロファイラーを使用して問題があるかどうか、いつ問題があるかを判断する必要があります。その場合にのみ、パフォーマンス上の理由からコードを変更することを検討してください。

于 2012-10-15T11:20:27.220 に答える
3

Java には構造体がなく、クラスのみがあります。Java のクラスは、クラスが C++ バックエンドにもあることを必ずしも意味しません。JVM が C/C++ で実装されているかどうかさえわかりません。他のどの言語でも可能です。

しかし、C++ JVM については、最適化しようとしていると思います。int や boolean などのプリミティブ (ボックス化されていないとは呼ばれません) 型は、通常、対応するプリミティブ型にマップされます (私の JNI の経験によると) が、構造体がないため、配置する必要はありません。

クラスフィールドを再配置しても、メモリ消費には影響しないとほぼ確信しています。それらが構造体にマップされていないという理由だけで。

于 2012-10-15T11:12:31.400 に答える
0

他の人が指摘しているように、Java ではこのレベルの詳細を実際に制御することはできません。ただし、メモリをそれほど細かく制御する必要がある場合は、 byte[] にインデックスを作成するか、直接ByteBufferのオフヒープを作成することで、自分でメモリを管理できます。

于 2012-10-15T11:49:15.080 に答える