web-dev-qa-db-ja.com

.NET JITでコンパイルされたコードはどこにキャッシュされますか?

.NETプログラムは最初にMSILコードにコンパイルされます。実行されると、JITコンパイラはそれをネイティブマシンコードにコンパイルします。

不思議なんだけど:

これらのJITコンパイルされたマシンコードはどこに保存されますか?プロセスのアドレス空間にのみ保存されますか?しかし、プログラムの2回目の起動は、1回目よりもはるかに高速であるため、このネイティブコードは、実行が終了した後でも、ディスクのどこかに保存されているはずです。しかしここで?

46
smwikipedia

メモリ。 canキャッシュする、それがngen.exeの仕事です。マシンコードを含み、GACに格納されているアセンブリの.ni.dllバージョンを生成します。これは、JITステップをバイパスして、後で自動的にロードされます。

しかし、それはあなたのプログラムが2回目に速く開始する理由とはほとんど関係がありません。いわゆる「コールドスタート」が初めてです。これは、ハードドライブ上のDLLを見つけるために費やされた時間によって完全に支配されています。 2回目にウォームスタートを行ったとき、DLLはファイルシステムキャッシュですでに使用可能です。

ディスクが遅い。 SSDは明らかな修正です。

Fwiw:これはマネージコードに限った問題ではありません。多くのDLLを含む大規模なアンマネージプログラムにもそれがあります。ほとんどの開発マシンに存在する2つの標準的な例は、MicrosoftOfficeとAcrobatReaderです。彼らはごまかします。インストールすると、RunレジストリキーまたはStartupフォルダーに「オプティマイザー」が配置されます。これらのオプティマイザが行うのは、メインプログラムが使用するすべてのDLLをロードして、終了することだけです。これにより、ファイルシステムキャッシュが準備されます。ユーザーが後でプログラムを使用すると、ウォームスタートが高速であるため、プログラムはすばやく起動します。

個人的には、これは非常に面倒だと思います。彼らが本当にすることは、ログイン後に開始したい他のプログラムの速度を低下させるからです。これは、OfficeやAcrobatであることはめったにありません。ブラストされた更新によって元に戻されたときに、必要に応じて繰り返し、これらのオプティマイザーを削除することにします。

このトリックも使用できますが、責任を持って使用してください。

73
Hans Passant

他の人が指摘しているように、あなたの場合、コードはプロセスごとにJITされ、キャッシュされません-2回目のロードで見られるスピードアップは、アセンブリのOSディスクキャッシング(つまり、メモリ内)です。

ただし、デスクトップ\サーバーバージョンのフレームワークには(OSディスクキャッシングを除いて)キャッシュはありませんが、別のバージョンのフレームワークにはJITされたマシンコードのキャッシングがあります。

興味深いのは、.Net Compact Framework(NETCF for Windows Phone 7リリース)で何が起こっているかです。最近の進歩により、JITされたコードが実際にキャッシュされているプロセス間でJITされたフレームワークコードが共有されることがわかりました。これは主に、携帯電話などの制約のあるデバイスでのパフォーマンス(ロード時間とメモリ使用量)を向上させるために実行されました。

したがって、質問への回答として、CLRのデスクトップ\サーバーバージョンにはJITされたコードの直接フレームワークキャッシュはありませんが、コンパクトフレームワークの最新バージョン(NETCF)にはあります。

参照:私たちは共有を信じています

http://blogs.msdn.com/b/abhinaba/archive/2010/04/28/we-believe-in-sharing.aspx

11
Tim Lloyd

JITでコンパイルされたマシンコードは、メソッドが初めて実行されるたびに、メソッドごとにメモリにキャッシュされます。ディスクにキャッシュされることはないと思います。

Windowsは、最初の実行時にプロセスで使用されるファイル(dll、リソースなど)を(メモリに)キャッシュするため、プロセスの2回目のロードが高速になる場合があります。 2回目の実行では、ディスクに移動する必要はありません。これは、最初の実行で実行された可能性があります。

NGen.exeを実行 でこれを確認して、アーキテクチャのマシンコードを実際にプリコンパイルし、1回目と2回目の実行のパフォーマンスを比較できます。私の考えでは、OSにキャッシュがあるため、2回目の実行はさらに高速になります。

7
Sam

つまり、ILはプログラムの呼び出しごとにJITコンパイルされ、プロセスアドレス空間のコードページに保持されます。 .NET実行モデルの詳細については、 Richter の第1章を参照してください。

2
lesscode

JITでコンパイルされたコードが保存されたり、メモリからスワップアウトされたりすることはないと思います。アセンブリの2回目の実行で認識されるパフォーマンスの向上は、依存するアセンブリがすでにメモリまたはディスクキャッシュにあるためです。

1
Philip Smith

はい、NGEN.EXEは、MSILバージョンがない場合でも、.NET実行可能ファイルのJITコンパイル済みバージョンをGACに配置します。私はそれを試しましたが、役に立ちませんでした。元のMSILバージョンもGACにあり、そこからロードされない限り、GACのJITバージョンは使用されないと思います。また、オンザフライのJITコンパイル(not NGEN)はキャッシュされないと思います。それらはプロセスメモリのみを占有します。

これは、MSドキュメントを読んだり、さまざまな実験から得られたものだと思います。私は「知っている」人々からの私の主張の確認または反論のいずれかを歓迎します。

1
Arra Avakian