.NET 8 の Blazor WebAssembly には Jiterpreter が搭載!
.NET 8 より前の Blazor WebAssembly では、AOT コンパイルを有効にしない限り、.NET アセンブリ内の IL コード (中間言語) は、WebAssembly 上で稼働するインタープリターによって逐次実行されます。インタープリター方式なので、演算処理性能的には極めて不利なのです。もちろん、遅すぎてどうにもこうにもならないということはなく、インタープリターにしては結構高速に動作し、多くの Web アプリケーションではさほど演算処理性能を要求しないため充分な性能です。ですが、やっぱりインタープリターである以上、限界はあります。
AOT コンパイルを有効にすれば、MSIL ではなく WebAssembly バイトコードが発行時に生成されるため、演算処理性能に関しては解決可能です。ただそれと引き換えに、発行時間が分単位と長くなり (まぁ、発行時間くらいは我慢できるケースも多いかもです)、コンテンツサイズが 2 倍かそれ以上に膨らみます。
そのような背景下、2023年11月にリリースされた .NET 8 では、Blazor WebAssembly の MSIL インタープリターに "Jiterpreter" と呼ばれる、一部コードを実行時に WebAssembly バイトコードネイティブに変換 (JIT、つまり Just In Time、"ちょうどそのときに" コンパイルする機能) して処理速度を稼ぐ、という技術が搭載されるようになりました。フルセットの JIT コンパイラではなく、あくまでも基本動作はインタープリターであるため、"JIT" + "Interpreter" = "Jiterpreter" という造語で呼んでいるようです。これは、.NET 8 における Blazor WebAssembly の MSIL インタープリターとしての機能であるため、プロジェクト側で何か指定や設定をすることなく、タダでついてきます。
つまり、.NET 8 の Blazor WebAssembly は、それより前の世代の Blazor WebAsembly より、演算処理性能が向上している、というわけです。
ということで、ではいったいどれくらい早くなるのか、かなり雑なベンチマークになりますが、.NET 6、7、8 それぞれの速度を比較してみました。
速度比較の題材
4032 x 2016 ピクセルの画像 (下図) を白黒画像化する、そのような Blazor WebAssembly アプリケーションを作成し、.NET 6、7、8 それぞれでリリース構成で発行して、それぞれ白黒画像化にかかる時間を計測します。
画像データは 1 ピクセルあたり 4 バイトで R、G、B、A の各値を1バイトで持ち、これを一次元の byte
配列に持ちます。この画像データ (byte[]
) を白黒画像化して上書き変更する処理を、以下のように実装しました。
public static void ConvertToGrayScaleByDotNet(int sx, int sy, byte[] pixelData)
{
for (var x = 0; x < sx; x++)
{
for (var y = 0; y < sy; y++)
{
var ir = (x + y * sx) * 4;
var ig = ir + 1;
var ib = ir + 2;
var r = pixelData[ir];
var g = pixelData[ig];
var b = pixelData[ib];
var m = (byte)Math.Round(0.3 * r + 0.6 * g + 0.1 * b);
pixelData[ir] = pixelData[ig] = pixelData[ib] = m;
}
}
}
ものすごくシンプルな演算処理ですね。
結果発表
では以下に測定結果です。
なお計測ですが、テスト用 PC 上でサーマルスロットリングの発生に注意しながら、各バージョン 5 回実行し、最後の 3 回の平均値を取ってみました。
対象プラットフォーム | 処理時間 (秒) |
---|---|
.NET 6 | 0.67 |
.NET 7 | 0.79 |
.NET 8 | 0.41 |
なぜか .NET 7 より .NET 6 のほうが 100 msec 以上速いのが気になりますが、さておき、.NET 8 では、フルの JIT ではないとはいえ、明らかに高速化されていることがわかります。.NET 7 に対して 1.8 倍以上、.NET 6 に対しても 1.6 倍近く高速化しています。
(ちなみに AOT コンパイルすると、処理時間は 0.10 秒にまで短縮されます。)
まとめ
多くの Web アプリケーションでは、ここまでの演算処理性能が求められることは少なく、そのような多くの Blazor WebAssembly アプリケーションではこの .NET 8 の Blazor WebAssembly における Jiterpreter 技術の恩恵も少ないのかもしれません。
とはいえ、.NET 8 に移行するだけで、それ以上の追加の手間も何もなしに、且つこれといったトレードオフもなく、演算処理性能の向上が見込まれるのは歓迎されるべきことでしょう。
以上です。
Happy Coding! :)