web-dev-qa-db-ja.com

圧縮されたJVMの裏技Oops

だから私はHotSpotでデフォルトで圧縮oopsが有効になっていることを理解していますVM now。それはJava SE 6u23以降からVMオプション-XX:+UseCompressedOops。 CPUキャッシュは64ビットサイズの参照を処理する必要がある場合よりも多くの参照を保持できるため、CPUキャッシュを効率的に使用できることを理解しています。しかし、私が理解していないのは、32ビットのJVMだけを使用すると、最大264 アドレス。

問題を簡単にするために、最大2つまで対処する方法4 メモリアドレスは2ビットだけを使用していますか?そのようなアドレス体系の可能なエンコード/デコードは何ですか?

19
Geek

圧縮oopの詳細な説明については、John Rose @ Oracleによる "Compressed oops in the Hotspot JVM" の記事を参照してください。

TL; DRバージョンは次のとおりです。

  • 最新のコンピュータアーキテクチャでは、メモリアドレスはバイトアドレスです。
  • Javaオブジェクト参照は、Wordの始まりを指すアドレスです1
  • 64ビットマシンでは、ワードアラインメントは、オブジェクト参照/アドレスの下位3ビットがゼロであることを意味します2
  • したがって、アドレスを3ビット右にシフトすることにより、64ビットアドレスの最大35ビットを32ビットワードに「圧縮」できます。
  • そして、3ビットを左にシフトすることで伸張を行うことができます。これにより、これらの3つのゼロビットが戻されます。
  • 35ビットのアドレス指定により、64ビットマシンの32ビット(ハーフ)ワードに適合する圧縮oopを使用して、最大32 GBのヒープメモリのオブジェクトポインターを表すことができます。

これはonlyが64ビットJVMで動作することに注意してください。その(最大で)32 GBのヒープを含むメモリをアドレス指定できる必要があります。1、つまり、64ビットのハードウェアアドレスを意味します(最新のCPU /コンピューターアーキテクチャ上)。

これを行うと少しペナルティがあることにも注意してください。つまり、通常の参照と圧縮された参照との間の変換に必要なシフト命令。ただし、反対に、消費される実際のメモリは少なくなります。とメモリキャッシュは通常、結果としてより効果的です。

1-これは、最新のコンピュータアーキテクチャがワード境界のメモリアクセス用に最適化されているためです。

2-これは、-XX:ObjectAlignmentInBytesを使用して配置をデフォルト(および最小)値の8バイトから増やしていないことを前提としています。

3-実際、メモリの節約はアプリケーション固有です。これは、オブジェクトの平均的な浪費、非参照フィールドに対する参照の比率などに依存します。オブジェクトの配置の調整を検討すると、さらに複雑になります。


問題を簡単にするために、最大2つまで対処するには4 2ビットだけを使用してメモリアドレス?そのようなアドレス体系の可能なエンコード/デコードは何ですか?

あなたは2に取り組むことはできません4 バイトアドレス。しかし、あなたはアドレス2ができます2 2ビットのワードアドレスを使用したワードアドレス(32ビットワードを想定)。すべてのバイトアドレスがワード境界で整列していると想定できる場合は、4ビットのバイトアドレスを2ビットの位置でシフトすることにより、2ビットのワードアドレスとして圧縮できます。

29
Stephen C

これは、32ビットJVM用ではありません。 64ビットJVMで発生する追加のオーバーヘッドを軽減するためです。オラクルのページはそれをうまく説明していると思います:

圧縮エラー

圧縮されたoopは、64ビットJavaヒープベースアドレスからの32ビットオブジェクトオフセットとして、管理されたポインター(JVMソフトウェアのすべてではないが多くの場所)を表します。それらはバイトオフセットではなくオブジェクトオフセットであるため、最大40億のオブジェクト(バイトではない)、または最大約32ギガバイトのヒープサイズをアドレス指定するために使用できます。それらを使用するには、それらを8倍にスケーリングし、Javaヒープベースアドレスに追加して、それらが参照するオブジェクトを見つける必要があります。

ソース

9
Enno Shioji

https://blog.codecentric.de/en/2014/02/35gb-heap-less-32gb-Java-jvm-memory-oddities/

この記事はこれをよく説明していると思います。奪われた:

JVMメモリレイアウトは8バイトのアドレス指定スキームを使用しているため、オブジェクトはアドレス0、8、16、24に配置できますが、2、7またはその他の8の倍数には配置できません。圧縮oopは仮想位置0にアドレス指定するだけです。実際のアドレス0、8、16、24の代わりに1、2、3。圧縮アドレスから実際のアドレスに取得するには、JVMはそれを3回左シフトする必要があります。簡単です。

4G * 8 = 32

0
Jiacai Liu

CompressedOops

記事から:すべてのポインターが圧縮されているわけではなく、圧縮されたものは32ビットの値であり、8倍にスケーリングし、64ビットのベースアドレスに追加して、参照するオブジェクトを見つける必要があります。

ここで、これらの32ビットポインターを使用して2 ^ 64ビットのメモリをアドレス指定することはできませんが、それらを使用して多くのObjectsにアクセスできることに注意してください。メモリ位置xにオブジェクトがある場合、x+1に別のオブジェクトを配置する方法はありません。そのため、すべてのメモリ位置にアクセスする必要はありません。

0
Kayaman