[Java, JavaScript] Nashorn Architecture and Performance Improvements in the Upcoming JDK 8u40 Release

原文はこちら。
https://blogs.oracle.com/nashorn/entry/nashorn_performance_work_in_the

[訳注]
原文はMarcus Lagergren (動的言語のパフォーマンス・アーキテクト)からのメール形式になっていますが、訳文では少々編集しています。

ここしばらくブログ投稿をご無沙汰して申し訳ありませんでした。ちょうどコードフリーズしたOpenJDK 8u40について、そしてNashornにどのような機能拡張を施したのかをこのタイミングで説明するのがよいと考えました。

8u40ではNashornコードジェネレータを書き換え、Optimistic type systemが搭載されています。

JavaScript、もっとはっきり言うと、任意の動的言語は、パフォーマンスの高いコードを簡単に生成するためのコンパイル時の情報を提供しません。これが、8u40のために、Nashorn Type Systemを再設計し、より良い、高速なコードを生成するようにした理由です。Nashornコンパイラの出力である、Javaバイトコードは、意図的に強く型付けされていますが、JavaScriptはそうではありません。ここに動的言語のASTを最適なバイトコードへ変換する重大な問題があります。Attila Szegedi、Hannes Wallnöfer、と共に、昨年来、この問題を解決するために膨大な時間を研究や実装に費やしてきました。

背景
伝統的に、JavaでJavaScriptランタイムを実装する際、数字と言われるものをJavaでdoubleとして表現でき、それ以外のものは全てObjectとして表現できます。これには、数字、int型、long型や、その他の静的に証明可能ではないプリミティブ型が含まれています。言うまでもなく、このアプローチは、内部で多くのボクシングをもたらすため、JVM上での動的言語の実行速度の面でかなりのボトルネックになります。JVMは、Javaのようなバイトコードの最適化が得意ですが、これは、Javaのようなバイトコードではありません。
Type transitions in the optimistic type system
Nashornは実際に大規模な静的型解析を実施するため、生成されたコードは、上記の保守的なシナリオに比べてはるかに優れたものになる、というのが、もう一つの8u40の新しい点です。とはいえ、まだ全ての型で証明できているわけではないため、そこでOptimistic Type Systemが出てきます。今回のOptimistic Type Systemは、任意の静的に証明できない型がintという、全てのデータ型でもっとも制限の厳しいデータ型と仮定します。実行時にこの仮定が間違っていることが判明した場合には、例えばObject型やdouble型であることがわかったフィールドをメモリやスコープからロードします。また、オーバーフローする32ビットの加算を実施する場合には、実行中のコードをより保守的なバージョンで置き換えます。つまり実行中に再生成します。Nashornは実行時のコード置換を容易にするためのsimple continuationをサポートしています。これは将来、例えば、仮想的なインタプリタ層とコンパイル済みバイトコード間で行き来するといった、様々な用途に使われる可能性がある機能です。

また、将来のこうした変更に対する保護のため、リンク時にCallsiteに渡した引数によって、バイトコードがどのように見えるのかを詳細に調べ、推測しています。
Octane benchmark scores, normalized on JDK 8. 
これにより、(静的な場合には)生成されたバイトコードが実行速度において最適なJava型を含むようになっています。このコスト(全てにはコストがかかります)は、コード生成に時間を要する、というところに現れます。具体的には、わずかにウォームアップでマイナスの影響があります。ウォームアップはJDK9における主要なR&D分野であり、この件を解決でき、またワークロードを改善し、HotSpotによりうまくコンパイルさせて、もっと最適化されたサイクルにすることができる、と自信をもっています。

NashornをJVMの動的言語のための一般的なプラットフォーム/ランタイムとする取り組みで、Optimistic Type SystemはNashornに対しコード生成を指示しているどんなASTともうまく統合されています。将来のJavaのリリースのためにこれらの計画をもっと固め、最終的にNashornが「JVM上の動的言語のためのLLVM」のようなものになることを願っています。楽観的な型付けの問題がすべての動的言語に戻ってきます。このことを証明するために、当社の優れた論文学生であるAndreas Gabrielssonが、TypeScriptをNashornで実行するために必要なほとんど全てのものを実装することに成功しました。これを書いている時点で、唯一の大規模な機能のモジュールが不足しています。中間レベルのコンパイラ層でJavaScriptを生成せずに、NashornはTypeScriptからバイトコードに直接到達します。これは非常に素晴らしいことであり、Nashornが既に拡張性が高いことを示しています。類似の環境でRubyやGroovyが実行されていることについて考えてきました。Nashorn TypeScriptはまだオープンソース化されていませんが、まもなくそうなることを期待しています。

optimistic typeを使って8u40のNashornを実行するには、 以下の引数を使う必要があります。
--optimistic-types=true
まだウォームアップの問題に対する解決策を入れる時間がなかった(それはすべてのものに影響するわけではないですが、問題が残っていることで迷惑を掛ける可能性があります)ため、Optimistic Type SystemはまだNashornのデフォルト設定・動作とはなっていません。これは過度に保守的のように思われるかもしれませんが、不必要に皆さんのウォームアップを壊したくなかったためにそのようにしました。

以前のリリースに比べると、Octane benchmarks suiteのようなもので、数桁のオーダーでの性能向上をお知らせできます。また、Avatarプロジェクト向けのREST、HTTPベンチマークにおけるネイティブまたはネイティブに近いパフォーマンスを報告することができます。このことについてかなり好感を持っています。いくつかのケースでは、Nashorn上のJavaScriptアプリケーションは、SpiderMonkeyやV8のようなネイティブランタイム上で実行した同じアプリケーションと同じくらい速く動作します。言うまでもなく、自分たちの仕事をかなり誇りに思っています。

しかも・・・
JDK 8u40のNashornは生成されたコードと、推測された型情報を実行時にディスクへキャッシュします。
これは、長いウォームアップを伴う大きめアプリケーションにおける最初のイテレーションだけが問題になることを意味します。同じコードを連続実行する場合には非常に素早く安定し、等しく良好なパフォーマンスで実行されるでしょう。


是非お試し頂き、気付いたことをお知らせください。何かご質問があれば、ドキュメントを読み、メーリングリスト nashorn-dev [at] openjdk.java.net に参加してお知らせください。TwitterでNashornチームをフォローすることもできます。
  • Jim Laskey: @wickund 
  • Sundararajan Athijegannathan: @sundararajan_a
  • Marcus Lagergren: @lagergren
  • Attila Szegedi: @asz
  • Hannes Wallnöfer: @hannesw 

近い将来、より多くのエントリをUpすることになるはずですので、ご期待下さい。ブログ執筆活動を休止していることに対し、申し訳なく思っております。

追伸
多言語ランタイムとしてのJVMや、そうした多言語ランタイムを促進するフレームワークとしてのNashornに関する情報に関心がある場合には、以下のプレゼンテーションが知的好奇心を満たすかもしれませんのでご紹介しておきましょう。

0 件のコメント:

コメントを投稿