BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース 必要メモリが少ないJRuby 1.1RC2のリリース

必要メモリが少ないJRuby 1.1RC2のリリース

JRuby 1.1 RC2がリリースされ(source)、RC1よりもかなりの改良が見られた。
- JRuby 1.1RC1より260もの問題点が解決された
- 大規模なIOリファクタリング
- JITされたメソッドのメモリ改良
   - JIT'されたメソッドの総数を制御
   - ランライムと戻りpermgen間のJITキャッシュをサポート
   - 生成済みメソッドのコードサイズを縮小(50から70%の縮小)
Oniguruma RegexエンジンのJavaポート(参考記事)は別として、JRuby 1.0に対するJRuby 1.1の最大の性能の改善はJust In Time (JIT)コンパイラーの導入で、RubyコードでJVMバイトコードにコンパイルするものである。しかしながら、JVM言語の実装が対処すべき問題も提 示する。

JRubyのJITで問題となっていることは、JVMにおいてバイトコードが管理される方法である。JVMでのバイトコードのロード可能な最小ユニットは クラスである。それゆえ、 RubyメソッドがJITされると生成されたコードは新たなクラスのメソッド本体に入れられ、ロードされる。しかし、これは潜在的にソースの問題メモ リーリークを引き起こしかねない。バイトコードがガーベッジコレクター生成であるPermGenにロードされ、それはデフォルトではかなり小さくたいてい64MBである。Nick Sieger氏は、 JITされたメソッドだけでこれがどれだけ迅速に埋められるのかを説明している。
コンパイルするためにRuby標準ライブラリを大いに使用し、プラグインを十二分に使用し、JRubyで使用可能なたくさんのメソッドを使用する重要な Railsのアプリケーションは、優に10000を超えるということを検討してみる。単一のJRubyメソッドクラスの平均的なオーバーヘッドは、およそ 8K(もちろんメソッドサイズにより変化)である場合、これはpermgen空間の80メガバイトまで占める可能性がある。(それとは対照的に、デフォル トのJVMのpermgen空間サイズは64メガバイトであるので、すでに限度を越えている)。
4つのRailsアプリケーションをそれぞれ4つのアクティブランタイムで1つのアプリケーションサーバにデプロイする場合、アプリケーションの実行にお よそ1.2ギガバイトのpermgen空間を検討しているだろう。(たいてい、Javaアプリケーションサーバで複数のアプリケーションを実行することは 一般的であるが、Railsアプリケーションの場合では、再検討する必要があるかもしれない)。

これは、非常に現実的な問題である。PermGenは一般的なJavaヒープのような振る舞いをする。決まったサイズがありPermGenがいっぱいになると、OutOfMemory例外が発行されて、最終的にJVMは終了する。

Nick Sieger氏は、RC2でのこの問題に対するさまざまなソリューションについて説明している。

こうした倍増していくコストのため、JRuby1.1がリリースされて間もなく、いく分抜本的な対策を講じて、それぞれのランタイムが2048回まで JITコンパイルするというメソッド回数の上限を設けた。しばらくしてしきい値ベースのアプローチでさえも、コンパイルされたメソッドの重複コピーで JRubyはまだ多くのpermgen空間を無駄にしていることが、明らかになった。そこで1.1RC2では、JIT キャッシュを導入し複数のランタイム間で、共有できるように設定した。


この問題のソリューションは既に.NETプラットフォームのDynamic Methods(source)として利用可能である。単一のメソッド本体でJavaクラスにRubyメソッドをコンパイルせずに、バイトコードはオブジェクトに重点を置 いて、メソッドオブジェクトに格納される。これらのDynamic Methodsは、一般のオブジェクトのような振る舞いをする。そしていったんそれ以上到達可能でなくなると、ガーベッジコレクションされる。John Roseが説明しているように、このアプローチはその他多くのオーバーヘッドを除去する(ブログ・英語)
動的言語の実装における1つの痛点が、コードを動的に管理している。実装者はメソッドの本体およびその本体の要求された呼び出しシーケンスへのリンケージに注目している一方で、コードを適切に配置するためJVMが要求する関連詳細がある。以下のような詳細である。
  • メソッド名
  • エンクロージングクラス名
  • その他の名前が付けられたエンティティーに関するさまざまなアクセス制限
  • クラスローダーおよびプ保護ドメイン
  • リンケージおよび初期化状態
  • クラス階層の配置(クラスが一度もインスタンス作成されていない場合でも)

こういった詳細は実装者の作業を阻害するものとなり、たいていの場合さまざまな例外オーバーヘッドの原因となる。指定された名前のクラス(およびクラス ローダー)は一度正確に定義される必要があり、その後でその名前(Class.forNameを経由)からのみリカバリー可能である必要があるので、 JVMは新たに定義されたクラスをその定義しているクラスローダーおよびシステム辞書と呼ばれるデータ構造に接続する必要がある。そしてその後のリンケー ジ要求を処理する。このような関係を築くには時間がかかる。その理由としては特に、さまざまなシステムロックを取る必要があるからである。また、GCによ る未使用コードの収集をさらに難しいのもにしている。
もちろん、.NETのDynamic MethodsはJVMでは利用できない。プロトタイプが利用可能なDa Vinci Machineプロジェクト(source)で研究がおこなわれているが、いつそのような機能が次回のJavaのリリースで利用可能になるのかは、 現時点では不明である。

原文はこちらです:http://www.infoq.com/news/2008/02/jruby-11rc2-release

この記事に星をつける

おすすめ度
スタイル

BT