Java,.NET,Ruby,あるいは Python などのマネージドコード (Managed Code) を実行するプロダクションサーバは,ますますその数を増している。ところが今日,これらのサーバ負荷を担うハードウェア製品やオペレーティングシステムの基本デザインは,この種の処理に対して最適化されたものになっていない。このために起こる,よく知られた問題のひとつが,ガベージコレクション (Garbage Collection/GC) 中に発生する処理停止である。
多くの企業システムアーキテクトや開発者にとって,プログラムをできる限りメモリ上に置くことと GC によるシステム停止,この2のトレードオフを図ることは,現在ではごく普通の課題である。エンタープライズ Java の場合,プログラムを分散してヒープを小さく保つことによって,この種の停止の影響を軽減することができる。さらに別のテクニックも利用されている。例えば,スループットに比べてレスポンス時間の問題が重要でない場合には,非同期コールを用いてより"バッチ的"な処理を行う方法などだ。
この種のソリューションはエンジニアリングアプローチとしては理にかなったものではあるが,理想的な結果でないことは明らかだ。Azul Systems の技術担当副社長である Gil Tene 氏は私たちとの対談において,現在の状況を DOS 時代の拡張メモリや改良メモリのモデルに例えてみせた。これらのメモリモデルは当時,PC が 640KB の制限を越えるメモリをサポートしている場合に,そのメリットを活用する目的で設計されたものだった。
私たちの経験に基づく見積では,一般的なエンタープライズシステムのワークロードを単一の Xeon コアで実行する場合であれば,現在では継続的に ~0.5GB/秒の新規オブジェクトを生成することは十分に可能です。最近はこのようなコアがソケットごとに6ないし8個ありますから,$20,000以下の市販システムでも 12~48個のコアを持っています。ですから最近の市販システムは(CPU能力がすべて有効な処理に利用されると仮定して),連続的に 5~15GB/秒のアロケーション速度がある,と見なすことができます。ただしこの数値(~0.5GB/秒)は不明確かつ主観的な事例のひとつに過ぎません。実際に確認できる値 (コアあたり 150MB~1GB強/秒の範囲) はワークロードの内容に影響されます。"革新的 (transformative)" なワークロード (例えばメッセージバス,Webアプリケーション,統合サーバ,DB中心のトランザクション型,データキャッシュなど) であればもっと高い数値が得られるでしょうし,数値計算中心のワークロード (Monte Carlo シミュレータ,暗号処理,圧縮処理,有限要素解析など) では低くなるはずです。
業界標準のベンチマークも参考データにはなりますが,私はこの手のベンチマークがどれも好きではありません。その主な理由は,実運用時の GC の影響を無視するように作られているからです。この種のベンチマークには,すべてに共通する盲点があります。それは GC が必要不可欠なものだ,という認識に欠けていること - どのベンチマークも,計測中 GC の対象外となって影響を受けないように意図的に作成されているか,あるいは最近のサーバの能力を使い切らないように計測されているのです。オブジェクトの世代管理方法にぴったり合わせて,計測時間中に圧縮 GC イベントを発生させるようなヒープの長期的乱れを避けるようにすれば,スループットの測定中,ベンチマークプログラムをメモリに貼りつけておくことは十分可能です。そうしておいて,計測時間外に発生したフル GC イベントが必然的に引き起こす外乱の影響は故意に無視してしまっているのです。こんなベンチマークでは,アプリケーションが現実の負荷状態で連続実行する場合の振る舞いの推測には役立ちません。ですがその結果を(いくつかの調査で行われているような)OP 当たりのアロケーションで測定することは可能です。そうすればデータを,特定のワークロードにおけるオブジェクトの割当 (とガベージの発生) の割合を投影したもの,と見ることができます。
例をあげれば:
SPECjbb2005 のアロケーション速度は ~0.01MB/OP です。Intel Xeon の1コアの処理能力が 70K~80K OP/秒 (複数のベンダが公表した最近の結果に基づく)ですから,コア当たりのアロケーション速度に換算すれば 700~800MB/秒になります。
SPECjAppServer2004 のアロケーション速度は ~0.55MB/JOP,Intel Xeon 1コアの能力が 430 JOP/秒程度なので,換算値は 236MB/秒になります。
ここで JOP とは,SPECjAppServer2004 ベンチマークのオペレーション単位(Java Operation の略だと思います)です - 詳細は www.spec.org 参照。このベンチマーク以外では意味のない単位ですが,同じベンチマーク同士の比較には利用できます。
編集注記::
上記の OP 単位値は こちら から参照したものです。
Azul Systems ではリードバリア(read barrier),ライトバリア(write barrier)をハードウェアに組み込んで直接サポートすることで,ガベージコレクション停止の問題を解決している。Cliff Click 博士が InfoQ で最近説明した ところによると,これは,
... よりシンプルな GC アルゴリズムへの切り替えを可能にします - シンプルなアルゴリズムは,並列化,スケール,同時化,堅牢化も容易なのです。私たちは数年前にアルゴリズムを切り替えました。その結果,私たちの GC は競合他社よりも1桁大きなヒープ(とアロケーション速度)を容易に扱うことができています。
Tene氏はしかし,市販のハードウェア,特に Intel や AMD の最新チップがマネージドコードのロードを十分サポートできるようになったため,Azul GC アルゴリズムがこの2社のプロセッサにも適用可能になった,と説明してくれた:
具体的には,EPT (Extended Page Table) 機能 (最初 Xeon 55xx に搭載され,56xx,65xx,75xx チップにも採用されている) を持った Intel チップと NPT (別名 AMD-V Nested Paging) を持った AMD チップが対象になります。これらの新しい仮想メモリアーキテクチャ仕様 (EPT,NPT) は,リードバリアと高速な仮想メモリマッピング更新能力を備えています。それが市販 x86 プラットフォームで,私たちの GC アルゴリズムの実行をサポートするのです。Vega プロセッサは,メタデータ参照時のビットフィールドチェックの実行や,GC 圧縮されたページ用の特殊な仮想メモリ保護など,特殊なリードバリア用命令を持っていますが,x86 ベースの JVM では,これと意味的に同じことを複数の x86 命令を使用して行います。GC で圧縮されたページを x86 仮想メモリサブシステムを使って再マップし,保護することで,同じようなリードバリア効果を達成し,非停止GCアルゴリズムの実行に必要なアルゴリズム的不変条件を維持するのです。"リードバリア" は JIT コンパイラが発行する命令のセットで,通常のインストラクション中に効果的にはさみ込まれます (最新の4イシューx86-64コアパイプラインには,そのための余地がたくさんあります)。仮想メモリの操作には,著しく高速になる仮想メモリマッピング更新(大部分の OS で提供されるものの 100倍以上)に対応するために用意された,新たな OS API を使用します。幸運なのは EPT/NPT に加えて,最新の x86コアが備えている堅牢なトランスレーション・ルックアサイドバッファ (Translation Look-aside Buffer/TLB) サポートが,数十GB/秒というアロケーション速度を維持するのに必要な性能を容易に実現してくれることです - 一方で,これほどの速度で処理を行うためには,(OSカーネルなどの)ソフトウェアスタックの改良が必要になります - そのために私たちは,マネージド・ランタイム・イニシアティブを立ち上げたのです。
マネージド・ランタイム・イニシアティブ (Managed Runtime Initiative) が目指すのは,総体的なアプローチである。スケーラビリティとレスポンス時間の改善に注目しながら,垂直的な構成要素とシステムスタック(ランタイム,カーネル,OS,ハイパーバイザなど)を越えたインターフェース拡張を行うことが目標だ。プロジェクトの元になっているのは OpenJDK (Java バージョン6) 拡張と,新機能やインターフェースを公開するためのローダブル Linux カーネルオブジェクト (LKO) ないしモジュールである。この2つはいずれも GPLV2 の下でリリースされる。
Azul では Linux カーネル用に,GC のために最適化されたメモリ管理機能,ポリシー適用機能,そして Red Hat Enterprise Linux 6,Fedora C12,Suse を対象とした新しいリソーススケジューラをリリースする予定だ。OpenJDK のリリースには,新たな JIT コンパイラ,無停止ガベージコレクタ,スケーラブルなランタイムなどが含まれる。Azul Systems がInfoQ に語ったところによれば,この JVM とLinux 拡張の組み合わせによってランタイムの実行で100倍の改善,オブジェクトのアロケーション速度(とサポートされるヒープサイズ)は2桁の増加が可能である。
このイニシアティブは,Java プログラム言語の製作者である James Gosling 氏のサポートを受けている。プレスリリース より
マネージド・ランタイム・イニシアティブと Azul の,オープンソースコミュニティへの貢献に期待しています。マネージドランタイムは90年代中頃から長い道のりを経て,現在では広く普及したアプリケーション環境となりました。その一方でシステムスタックの他部分については,ニーズを満たす進化を遂げていないのが現状です。このイニシアティブはシステムスタックに新たな機能を導入して,マネージドランタイムが自由に成長と進化を続けるようにしてくれることでしょう。
自社の知的財産の重要部分をオープンソースにする,という彼らの決定は大胆なものだ。Azul Systems は急成長を遂げていて,直近の第1四半期決算では前四半期比 64% の増収を 発表している。現在の目標は,パートナーや ISV,ベンダからサポートを受けて,最新の技術を Windows .NET,Ruby,Python など他のプラットフォームやランタイムに進出させることだ。それに続く目標は,Linux と OpenJDK を最適化したパッケージ製品のリリースであるが,こちらはベンダの参加やサポートによるだろう。