👌

アプリの起動速度を試すとWPFよりもWinUI 3+NativeAOTの方がだいぶ速いようです(ただし0.5秒未満の差)

に公開

概要

WPFは起動が遅い。とよく聞きます。実際にどれくらい遅いものか、WPF以外と比べたらどうなのか、というのを試してみました。ここでは空っぽの画面を表示するだけのアプリの起動時間を試しているため、画面が複雑になって来るとまた違うかもしれません。

最初に結論まとめ

WPF、WPF+ReadyToRun、WPF(.NET Framework)、WinUI 3+NativeAOT、ネイティブC++のウインドウを試しました。.NETは8、.NET Frameworkは4.8.1です。

ログオンからスタートアップアプリ起動までが15秒くらいの環境で試すと、WPFは少し遅いです。WPFよりもWinUI 3やネイティブの方が、0.5秒弱くらい速いようです。大差無いとも言えますし、0.5秒違えば体感でだいぶ違ってくるので大きいとも言えます。起動速度にこだわる用途ではWinUI 3+NativeAOTの採用も選択肢になりそうです。

詳しく

実際にシンプルなアプリを作って計測してみました。と言っても、適当な1つの計測環境で数回ずつ測っただけなので、数字はあまり正確ではありません。大まかにどんな傾向があるかを見るくらいに捉えてください。

計測に使ったアプリ

テンプレートから生成しただけで画面には何も追加しない状態のコードに、画面が表示されたくらいのタイミングで「プロセス起動からの経過時間」の取得を行うコードを追加したもの。

https://github.com/suusanex/measure_dotnet_app_boot

計測条件

  1. 次の内容のVM
    1. Windows 11 x64 24H2
    2. CPUコア2
    3. メモリ8GB
    4. ※他VMとハードを共有しているためストレージ等の性能がブレる可能性有り
  2. ローカルアカウントの自動ログオン設定
  3. 対象アプリだけをスタートアップ登録(Startupフォルダへショートカット配置)
  4. 再起動直前のスナップショットを作成し、そこへ戻してからすぐ計測

計測内容

  1. 目視で、ログオン画面開始から、アプリの画面表示までの時間を計測
  2. アプリ内の処理で、画面表示時点の、プロセス起動からの経過時間を計測

計測結果1 ログオン開始~スタートアップ起動

複数回計測したものはカンマ区切りで記載。

対象 計測結果
.NET 8 18s,14s
.NET 8 ReadyToRun 15s,17s,15s
.NET Framework 4.8.1 15s,14s
ネイティブC++ 16s,14s
WinUI 3 NativeAOT(自己完結) 16s,14s

計測結果2 プロセス起動からの経過時間

複数回計測したものはカンマ区切りで記載。

対象 計測結果
.NET 8 0.68s,0.50s
.NET 8 ReadyToRun 0.52s,0.49s,0.57s
.NET Framework 4.8.1 0.32s,0.31s
ネイティブC++ 0s,0s
WinUI 3 NativeAOT(自己完結) 0.09s,0.18s

計測結果考察

プロセス内では.NET 8では0.5~0.6秒程度なのに対し、WinUI 3は0.1~0.2秒でネイティブは0秒。.NET FWはその中間くらい。ということで速さは「ネイティブC++ > WinUI 3+NativeAOT >> .NET FW > .NET 8」といった順位になりそうです。

ネイティブC++が最速なのは当然として、WinUI 3のNativeAotはだいぶ速くなった印象ですね。

その程度の差のため、スタートアップに15秒程度を要している計測環境では、「スタートアップの起動にかかる時間」という観点だとほとんど差が見えませんでした。少なくとも空っぽのアプリについては、スタートアップ用途では気になるほどの差はなさそうです。

しかし0.5秒弱の差はあるので、狙って起動した時の体感起動速度はありそうです。そこにこだわる場合はWinUI 3の検討も選択肢になると思います。(ランタイム配布等の他の条件を満たせれば、ですが)

まとめ

WPFは起動が遅い印象はありましたが、少なくともシンプルなアプリでは意外とそれほどの差はありませんでした。しかしWinUI 3+NativeAOTのほうが0.5秒弱くらいは速そうなので、その差にこだわる用途では検討アリだと思います。

Discussion