kagamihogeの日記

kagamihogeの日記です。

JEP 345: NUMA-Aware Memory Allocation for G1をテキトーに訳した

http://openjdk.java.net/jeps/345

JEP 345: NUMA-Aware Memory Allocation for G1

Owner    Sangheon Kim
Type    Feature
Scope   JDK
Status  Candidate
Component   hotspot/gc
Discussion  hotspot dash gc dash dev at openjdk dot java dot net
Effort  M
Duration    M
Duplicates  JEP 157: G1 GC: NUMA-Aware Allocation
Reviewed by Mikael Vidstedt, Stefan Johansson, Thomas Schatzl
Endorsed by Mikael Vidstedt
Created 2018/09/06 22:46
Updated 2018/11/22 15:30
Issue   8210473

Summary

NUMA-awareなメモリアロケーションの実装により大型マシンのG1パフォーマンスを向上する。

Non-Goals

  • G1以外のコレクションのサポート。
  • LinuxSolaris以外のOSのサポート。
  • G1コレクターのその他のパーツ、task queue stealing, remembered sets or refinementなど、をNUMA-awarenessにすること。

Motivation

近年のマルチソケットマシンはnon-uniform memory access (NUMA)を持つようになっており、これは各ソケットやコアとのメモリアクセスが必ずしも等しくありません。ソケット間のメモリアクセスは異なるパフォーマンス特定を持ち、遠くのソケットへのアクセスは基本的にはレイテンシもかかります。

parallel collector(-XX:+UseParallelGC)は既にNUMA-awareになっており、複数ソケットで単一JVMを動かす設定のパフォーマンス向上に寄与してきました。一方HotSpotコレクタはその恩恵を受けておらず、vertical multi-socket NUMA scalingを上手く使えていないことを意味します。とりわけ大規模エンタープライズアプリケーションは複数ソケット上で巨大なヒープを使用する傾向にある一方、単一のJVM内で実行する管理性の利点を欲しています。G1コレクタを使用する顧客でスケーリングのボトルネックがますます増していくのを我々は目にしています。

Description

G1のヒープは固定サイズのリージョンで構成されます。通常リージョンは物理ページのセットで、ラージページ(-XX:+UseLargePages)の場合、いくつかのリージョンは単一の物理ページを構成する可能性があります。

最近の近代的なOSは、プラットフォームのメモリトポロジへのクエリと、特定のlocality group(以降、lgrp)から優先的にマップされる物理メモリのためのインタフェースを備えています。lgrpはコレクタが使用可能です。JVMが初期化されると、all regions are evenly split between the total number of available lgrps and touched by threads bound to the same lgrps so that they are preferentially allocated on that lgrp. 全てのリージョンで開始時にリージョンのlgrpを固定することは少々柔軟性が足りませんが、この欠点を以下の拡張により緩和します。

リージョンはmutatorsのメモリアロケートかGC中にsurvivor objectsのコピーに使用します。これらのリクエストが発生すると、G1はスレッドがアロケートされている同一のlgrpからフリーなリージョンを優先的に選択します。つまり、オブジェクトはyoung generation中は同一のlgrpに存在し続けます。もし、mutatorのリージョンアロケーション中に同一lgrpからフリーなリージョンが無い場合、G1はGCをトリガ―します。別のアイデアとしては、フリーなリージョンの距離順で最も近いlgrpから先に検索する、があります。

old generationで同一lgrpにオブジェクトを保持し続けるようなことは特にしません。

Humongous regions*1はこのアロケーションポリシーからは除外します。このリージョンに対しては特に何もしません。

Testing

-XX:+UseNUMAオプションを付けての既存テストであらゆる正しさの問題(correctness issues)を洗い出せると思われます。本JEPのテストはNUMAのハードウェアを使用する想定です。

NUMA awareアロケーションをオフ時でもオリジナルのコードとパフォーマンスの差は無いと思われます。

Risks and Assumptions

大半の短命オブジェクトはそのオブジェクトを割り当てたスレッドでアクセスする、と我々は捉えています。これは確かにたいていのオブジェクト指向プログラムの短命オブジェクトの大半で事実です。しかし、この仮定が保留となるプログラムがあり、ある条件下ではパフォーマンス劣化の可能性があります。また、本JEPのメリットは基底システムのNUMAnessエクステントの相互作用と、システム上でlgrp間をマイグレートするスレッドの頻度に、特に負荷が高い場合に、依存します。

*1:https://www.slideshare.net/SparkSummit/kaczmarek-yi によると「リージョンサイズの1/2以上大きいラージオブジェクトのためのold regions. このオブジェクトはヒープの連続リージョンに保存される。」

JEP 344: Abortable Mixed Collections for G1をテキトーに訳した

JEP 344: Abortable Mixed Collections for G1

http://openjdk.java.net/jeps/344

Owner    Erik Helin
Type    Feature
Scope   Implementation
Status  Candidate
Component   hotspot/gc
Discussion  hotspot dash gc dash dev at openjdk dot java dot net
Effort  M
Duration    M
Reviewed by Mikael Vidstedt, Stefan Johansson, Thomas Schatzl
Endorsed by Mikael Vidstedt
Created 2017/10/27 09:56
Updated 2018/11/10 14:25
Issue   8190269

Summary

G1 mixed collectionsのポーズが指定時間超過時にアボート可能にします。

Non-Goals

G1のすべてのポーズをアボート可能にする。

Motivation

G1の目標の一つは、コレクションポーズにおけるユーザ指定のポーズ時間を満たすことです。G1は高度な分析エンジンを有しており、これはコレクション中に実行すべき作業量を選択するのに使います(一部アプリケーションの振る舞いに依存)。この選択結果はcollection setと呼ばれるリージョンのセットになります。collection setが決定および開始されると、そのcollection setの全リージョンのすべての生存オブジェクトをG1は停止せずに収集します。この振る舞いだと、ヒューリスティックが巨大なcollection setを選択する場合、G1が指定ポーズ時間を超過する場合があり、これは例えばヒューリスティックが"古い(stale)"データを参照するなどしてアプリケーションの振る舞いが変化する場合に発生します。これは特にmixed collections中に発生し、collections setが多数の古いリージョンを保持している場合が多いです。よって、ヒューリスティックが繰り返し誤ったコレクション作業を選択するのを検出するメカニズムが必要で、これがあれば、G1は各ステップでインクリメンタルにコレクション作業を実行し、各ステップ後にコレクションをアボート可能です。こうしたメカニズムによりG1は指定ポーズ時間をより守れるようになります。

Description

collection setのヒューリスティックが連続して多数のリージョンを誤って選択するのを、G1が検出したとき、mixed collectionsをよりインクリメンタルなものにスイッチします。collection setを2つのパート、必須とオプショナル、にスプリットします。必須パートはG1がインクリメンタル処理出来ないcollection setのパート(例:young regions)で構成されますが、効率を高めるためのold regionsを含む場合もできます。このパートは、一例としては、predicted collection setの80%になります。predicted collection setの残り20%はold regionsのみで構成され、オプショナルパートを形成します。

G1の必須パートのコレクション終了後、G1はより細粒度でオプショナルのパートのコレクションを、もし時間が残っていれば、開始します。オプショナルパートのコレクションの粒度は、一度に最大で一つのリージョン*1、残り時間に依存します。任意数のオプショナルcollection setパートのコレクション完了後、G1は残り時間に応じてコレクションの停止を決定します。

予測処理が正確になると、コレクションのオプショナルパートが縮小します。これはすべてのcollection setが必須パートになるまで行います(つまりG1はヒューリスティックに完全に依存する)。再度、予測処理が不正確になると、次回のコレクションは必須とオプショナルパートの両方を再び含むようになります。

Alternatives

  • 間違った予測処理をしないように分析エンジンとヒューリスティックを改善する。これ自体は興味深い目標ですが、ヒューリスティックはそれ以前のアプリケーションの振る舞いに依存する事を考えると、100%正確なヒューリスティックを得るのは不可能です。とはいえ、ヒューリスティックの改善は本JEPの必要性の低下に繋がります。
  • 予測処理に関する"安全マージン(safety margin)"を常に取る。たとえば、予測処理がxを返す場合、0.8 * x(20%の安全マージン)を常に取ります。これはおおむね動作すると思われますが、G1が指定ポーズ時間の80%のみ使うという意味になるので、予測処理のパフォーマンスが最善にならなくなります。
  • mixed collectionsのアボートに既存のevacuation failure mechanismを再利用する。この代替案は却下されており、その理由はアボート時にコレクションが任意のリージョンを解放する保証が無いためです。本JEPで提案するメカニズムでは、collection setの再生によってメモリ空間の再利用が進むことを保証します*2

Testing

実装を構成する個々のC++のパーツをユニットテストする。アボート可能なmixed collectionsのコードはG1 GCの中核部分なので、このコードは既存テストが使えます。

Risks and Assumptions

  • 必須とオプショナルにコレクションを分ける場合、オプショナルなcollection set用の追加データを保持する必要があります。このことは多少のCPUオーバーヘッドを課すことになり、このオーバーヘッドは1%未満でオプショナルなcollection setを使うmixed collectionsでだけ発生します。
  • オプショナルなcollection setを使用するmixed collections中のネイティブメモリ使用率が上がる可能性があります。オプショナルパート内で追加のリージョンポインターをmixed collection中はトラッキングする必要があるためです。

*1:at most down to one region at a time. 訳に自信無し

*2:The mechanism we propose guarantees space reclamation progress by reclaiming the space of the collection set on a region basis, which is G1's granularity of space reclamation. が原文。最後の方のwhich~あたりが上手く訳せんくって本文には含めていない

JEP 334: JVM Constants APIをテキトーに訳した

http://openjdk.java.net/jeps/334

JEP 334: JVM Constants API

Author   Brian Goetz
Owner   Vicente Arturo Romero Zaldivar
Type    Feature
Scope   SE
Status  Candidate
Component   core-libs / java.lang.invoke
Discussion  amber dash dev at openjdk dot java dot net
Blocks  JEP 303: Intrinsics for the LDC and INVOKEDYNAMIC Instructions
Reviewed by Alex Buckley
Endorsed by Brian Goetz
Created 2018/05/15 21:52
Updated 2018/11/13 11:31
Issue   8203252

Summary

中核であるクラスファイルとランタイムアーティファクトで名目上の記述(nominal descriptions)*1、ここではコンスタントプールからロード可能な定数、のためのAPIを導入します。

Motivation

すべてのJavaクラスファイルはconstant poolを持ち、ここにバイトコード命令用のオペランドを格納しています。constant poolのエントリは、クラスとメソッドなどのランタイムアーティファクトか文字列と数値などの単純な値、のいずれかを持ちます。これらのエントリは、ldc命令("load constant")でオペランドとして振る舞うため、loadable constantsと呼ばれています。これらはinvokedynamic命令のブートストラップメソッドのstatic引数リストにも出てきます。ldcinvokedynamic命令を実行すると、loadable constantは通常のJavaの型であるClass, String, intなどの "live" な値に解決されます。

classファイルを操作するプログラムはバイトコード命令を扱う必要があり、loadable constantも同様です。ただ、loadable constantsを扱う標準のJava型は不十分です。文字列(CONSTANT_String_infoエントリ)のloadable constantは"live" なStringオブジェクトの生成が単純なので許容範囲内ですが、クラス(CONSTANT_Class_infoエントリ)のloadable constantは"live"なClassオブジェクトはクラスローディングの正確さと一貫性に依存するため困難を伴います。クラスローディングには多数の環境依存と失敗理由が存在します。要求クラスが存在しない、リクエスト元からアクセス不能、クラスローディングがコンテキストで変化、ロードするクラスに副作用がある、クラスローディングが全く出来ない場合もあります(あるクラスがコンパイル中かjlink中なのでクラスがまだ無いかロード不能など)。

よって、もし、クラスとメソッドを操作可能で、メソッドハンドルと動的に計算される定数など既知のアーティファクトを減らせれば、 loadable constantsを扱うプログラムはシンプルになります。このために、純粋な名目上の形式(in purely nominal form)を使用します。

こうした種類のライブラリとツールは、loadable constantsを記述する単一の標準があることで、恩恵を受けられます。

Description

loadable constant各種を記述するための、値ベースなシンボリックリファレンス(value-based symbolic reference)(JVMS 5.1)型を、新規にjava.lang.invoke.constantパッケージに定義します。シンボリックリファレンスは、クラスローディングやアクセシビリティコンテキストとは別途に、純粋な名目上の形式でloadable constantを記述します。いくつかのクラスはそのクラス自身のシンボリックリファレンスとして振る舞えます(例 String)。リンク可能な定数用にシンボリックリファレンス型(ClassDesc, MethodTypeDesc, MethodHandleDesc, DynamicConstantDesc)を定義します。これらの型は定数を記述する名目情報(nominal information)を持ちます。

API仕様のドラフトスナップショットはこちらで、JEP 303に関する詳細情報はcompanion documentにあります。

Dependencies

このJEPは元はJEP 303 (Intrinsics for the LDC and INVOKEDYNAMIC Instructions).のサブ機能でした。現在JEP 303はこのJEPに依存します。

*1:うまい日本語が見つからず怪しい訳語を当てている……