2021年05月28日
川俣晶の縁側ソフトウェア技術雑記 total 5063 count

Blazorの実行速度はAOTビルドでどれぐらい速くなるか? 【驚異の大加速】

Written By: 川俣 晶連絡先

前提 §

 C#のコードはデスクトップで実行する場合と比べてBlazorでは基礎体力として60倍ぐらい遅いことが分かっていた。

 遅い理由は.NETのコードをWASMのコードで解釈して実行していたかららしい。

 . NET 6 Preview 4ではAOTビルドで直接WASMのコードを生成でき、6倍高速化できるという。

 実際にどの程度高速化できるのだろうか?

結果 §

 以前60倍遅いという結果を得たベンチマークのプログラムをそのまま使用して速度を調べた。なお、実行はいずれも手元のデスクトップ上のChromeで実行されているので、比較条件は同じである。

 なお、ソースコードはこのページの後ろに付けたとおり。

従来ビルド §

testNum 00:00:34.7790000

testNum2 00:03:05.9170000

AOTビルド §

testNum 00:00:03.2040000

testNum2 00:00:04.8470000

考察 §

 6倍速いという主張はおそらく平均であって、基礎体力だけ比較すれば60倍は速いことが分かった。つまり、デスクトップ上のC#コードに遜色ない速度で走ることが分かった。ライブラリ関数に依存する割合の多いtestNumでも10倍ぐらい速い。

 しかしながら、以下の問題があるため、効果は限定的である。

  • WASMへのコンパイルは配置時にしか実行されない。デバッグ実行には使えない。
  • WASMへのコンパイルが猛烈に遅い。気軽に繰り返せるものではない。
  • AOTコンパイルの準備に手間が掛かりすぎる

 これらの問題は、改良によって取り除かれていくと思うので、将来に期待しよう。

 Blazorの未来には期待が持てる。

ソースコード(抜粋) §

using System;

using System.Runtime.CompilerServices;

using System.Text;

namespace ClassLibrary1

{

    public class Bench

    {

        private static int ext1 = 12;

        private static int ext2 = 34;

        private static int ext3 = 56;

        private static int ext4 = 78;

        private static int testNum()

        {

            int sum = 0;

            for (int i = 0; i < 100000000; i++)

            {

                sum += i + ext1 - ext2 * ext3 / ext4;

                sum += (int)(Math.Sin((double)(i/100))*100);

            }

            return sum;

        }

        private static int testNum2()

        {

            int sum = 0;

            for (int i = 0; i < 1000000000; i++)

            {

                sum += i + ext1 - ext2 * ext3 / ext4;

            }

            return sum;

        }

        public static string DoOne(Func<int> act, string label)

        {

            DateTime start = DateTime.Now;

            act();

            return $"{label} {DateTime.Now - start}\r\n";

        }

        public static string DoItAll()

        {

            StringBuilder sb = new StringBuilder();

            sb.Append( DoOne(testNum, "testNum"));

            sb.Append(DoOne(testNum2, "testNum2"));

            return sb.ToString();

        }

    }

}