.NET Framework 4.6 の新しい 64 bit JIT コンパイラーについて
こんにちは、Visual Studio サポート チームです。
今回は .NET Framework 4.6 から導入された 64 bit アプリケーション用の新しい JIT コンパイラー (コード ネーム RyuJIT) についてご紹介します。
概要
従来の 64 bit 向け JIT コンパイラーでは、32 bit 向けの JIT コンパイラーと比較してパフォーマンス面で劣る問題がありました。
例えば、コントロール数の非常に多い画面を表示する際、64 bit アプリケーションでは画面の表示までにとても時間がかかるケースがありました。
.NET Framework 4.6 から導入された新しい JIT コンパイラー (RyuJIT) ではこの点を大きく改善し、64 bit アプリケーションの JIT コンパイルにかかる時間を大幅に短縮しています。
RyuJIT の詳細については、開発チームのブログ記事もご参照ください。 (いずれも Preview バージョンの段階で執筆されたものであり、Preview 版固有の記述も含まれておりますことご了承ください。)
RyuJIT: The next-generation JIT compiler for .NET
https://blogs.msdn.com/b/dotnet/archive/2013/09/30/ryujit-the-next-generation-jit-compiler.aspx
The JIT finally proposed. JIT and SIMD are getting married.
https://blogs.msdn.com/b/dotnet/archive/2014/04/07/the-jit-finally-proposed-jit-and-simd-are-getting-married.aspx
動作条件
RyuJIT は .NET Framework 4.6 以降の 64 bit アプリケーションの既定の JIT コンパイラーとなっています。
このため、特別な設定を行わなくとも、バージョン 4.6 以上の .NET Framework で動作する 64 bit アプリケーションであれば、RyuJIT が利用されます。
なお、.NET Framework 4.x をターゲットにビルドされたアプリケーションは、実行環境にそれよりも新しいバージョンの .NET Framework 4.x がインストールされている場合、その新しいバージョンの .NET Framework 上で動作します。
例えば、.NET Framework 4.5 をターゲット フレームワークに指定してビルドされた 64 bit アプリケーションを .NET Framework 4.6 がインストールされた環境で実行した場合は、アプリケーションは .NET Framework 4.6 上で動作し、JIT コンパイラーとしては RyuJIT が利用されます。
RyuJIT が利用される条件についてまとめると、以下のようになります。
・アプリケーションの実行環境に .NET Framework 4.6 以上がインストールされている。
・アプリケーション ビルド時に指定されているターゲット フレームワークが .NET Framework 4 以上である。
・アプリケーションは 64 bit プロセスとして動作する。
・後述の RyuJIT を無効化する設定が行われていない。
既知の問題・注意事項
.NET Framework 4.6 に含まれる形でリリースされた RyuJIT ですが、これまでに以下の問題が報告されています。
1) アンセーフ コードでポインタ変数等を使用するコードで AccessViolationException が発生する
2) Tail Call 最適化の問題
3) 特定の利用方法でパフォーマンスが従来の JIT より低下する問題
上記のうち 1)、2) については、.NET Framework 4.6.1 で修正されています。また、3) については弊社の開発部門にて修正が検討されている状況です。
1) は特定のコード パターンで発生する再現性のある問題です。アンセーフ コードでポインタ変数を使用する処理を実行した際に AccessViolationException が発生する場合、この問題に該当する可能性がありますので、.NET Framework 4.6.1 をインストールして問題が解消するかご確認ください。
2) の問題の詳細については、弊社開発部門のブログにて詳しい情報を公開しておりますので、こちらをご参照ください。
RyuJIT Bug Advisory in the .NET Framework 4.6
https://blogs.msdn.com/b/dotnet/archive/2015/07/28/ryujit-bug-advisory-in-the-net-framework-4-6.aspx
3) については、以下のサポート技術情報にて詳細が公開されております。
Performance issue when you use WCF to send XML SOAP messages in the .NET Framework 4.6
(英語原文) https://support.microsoft.com/en-us/kb/3076436
(日本語訳) https://support.microsoft.com/ja-jp/kb/3076436
上記のほか、最終的に生成されるネイティブ コードが RyuJIT と従来の JIT コンパイラで異なる場合がある点にご留意ください。これは、最適化の改善や使用される CPU 命令の違いによるものですが、アプリケーションの動作ロジックに相違が生じるものではなく、通常、互換性の問題となることはありません。
ただし、演算処理に使用される命令や演算処理の実行パスが異なることにより、浮動小数点数演算の有効桁外で演算結果に差異が生じる可能性はあります。RyuJIT の利用に限ったものではありませんが、浮動小数点数の扱いでは有効桁数や演算誤差に十分ご注意ください。
参考 : 浮動小数点を利用する際に知っておきたいこと
https://blogs.msdn.com/b/jpvsblog/archive/2014/10/28/10567928.aspx
RyuJIT を無効化する方法
やむを得ず従来の 64 bit JIT コンパイラを利用する必要がある場合は、RyuJIT を無効化することも可能です。RyuJIT を無効化するには以下の 3 とおりの方法があります。
方法 1 : アプリケーション構成ファイルに useLegacyJit 要素を追加して、アプリケーションごとに設定する方法
方法 2 : COMPLUS_useLegacyJit 環境変数を使用する方法
方法 3 : レジストリ キーに useLegacyJit を追加してシステム ワイドに設定する方法
方法 1 では、アプリケーションごとに設定を変更することが可能です。方法 2 では、システムの環境変数を変更してシステムワイドに適用したり、コマンド プロンプトから SET コマンドを実行してコンソール セッションごとに設定を変更することが可能です。
それぞれの方法の詳細については以下のページを参照ください。
Disable RyuJIT
https://github.com/Microsoft/dotnet/blob/master/docs/testing-with-ryujit.md\#disable-ryujit
参考
JIT コンパイルは .NET Framework アプリケーションの実行過程において、中間言語 (MSIL) のコードをネイティブ コードに変換する処理です。JIT コンパイルの詳細については、以下のドキュメント等をご参照ください。
MSIL からネイティブ コードへのコンパイル
https://msdn.microsoft.com/ja-jp/library/k5532s8a(v=vs.110).aspx#compiling_msil_to_native_code