ネコのために鐘は鳴る

寺院に住み着くパソコ〇好き

(C#) LINQPad で JIT のネイティブコンパイル結果を見る

LINQPad について

LINQPad は C# 用の簡易実行環境ツールです。簡易といいつつも Nuget Package も参照できるうえ、IDE と遜色ないぐらいのデバッグ機能があります。 むしろ、REPL 的に1行ずつ結果を見ながら追記したり、書き捨てのコードを試し書きするなどの用途では圧倒的に使いやすいです。(わざわざ書き捨てのコードのために Visual Studio からプロジェクト作ったりするの面倒ですよね)

書き捨てのコードの試し書きなら無料版でも十分使えます。(Nuget Package との連携機能がない・ブレークポイントが貼れないなどのデメリットあります)

C# をよく使う人で無料版で気に入ったなら有料版 (Premium) が圧倒的におすすめです。追加課金も使用期限も一切ない買い切りで、個人1ユーザーだと最上位版の Premium が1万円ぐらい。現時点の最新の LINQPad 7 は .NET6 も対応してます。旧バージョンの有料ライセンスを持っていたら、最新版のライセンスが半額以下で買えた気がします。

LINQPad で何ができるかは調べたら出てくるので省きます。

LINQPad - The .NET Programmer's Playground

私は Premium 版を買っているので、以降 Premium 版前提で話を進めます。無料版でどこまでの機能が使えるか把握していません。

コンパイル結果 (IL+JIT) を見る

コードを書いて F5 で実行後、結果のパネルの「Results」を 「IL+Native」に切り替えると、コンパイル結果の IL を表示できます。さらに「Show Native Disassembly」を押すと JIT コンパイル結果のネイティブのアセンブリも表示できます。

f:id:ikorin2:20220301054837p:plain

この x64 の JIT コンパイル結果は最適化されてないデバッグビルドの結果です。ネイティブコンパイル結果を好んで見るような変態が見たいのは、おそらく最適化が入ったリリースビルドだと思います。

ここで先ほどの画像の C# コードの先頭に、#LINQPad optimize+ というプリプロセッサディレクティブが意味ありげにコメントアウトしてあります。これをコメントを外すと最適化が入ったコンパイル結果に変わります。

f:id:ikorin2:20220301055709p:plain

コンパイル結果がガラッと変わってすっきりしました。最適化なしではインライン展開されていなかった Foo(1, 2) の呼び出しも、最適化後では定数の3に変わっていますね。(x64 の Main() 関数内 L0004 mov ecx, 3 の部分)

この #LINQPad optimize+ は LINQPad の専用のプリプロセッサディレクティブであるため、もちろん Visual Studio で書いても何の効果もありません。

また、メニューの「Edit」→「Preferences」を開いて「Query」→「Compiler Optimization Default」の設定から、デフォルトのビルドを最適化ありにすることもできます。しかし、普段 LINQPad でコードの試し書きなどする人はリリースビルドにするとブレークポイントが効かなくなるなどのデバッガビリティに影響が出ます。LINQPad の使い方を考えると、デフォルトをリリースビルドにするのはあまりお勧めしません。

f:id:ikorin2:20220301060341p:plain

ちなみに、ここで見られるネイティブコンパイル結果は JIT コンパイル結果であり、Unity の IL2CPP を通したネイティブコンパイルとは別物なのでお間違いのないように。