0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【C#】8月の AoT 自由研究

Posted at

はじめに

お盆休みに AoT 関係の知見が得られたため記事にしようと思います。

レンタルサーバーで C# AoT が動いた

前回の記事 で C# AoT が動かなかった問題が解消しました。
サーバーと同じ Linux 環境を用意してコンパイルすると動作します。

今回 Rocky Linux という OS に触りました。WSL にインストールして進めようとしたものの ubuntu と処理系が違って .NET のインストールにかなり手間取りました。Copilot がないとやらなかったんじゃないかなと思います。Copilot は環境構築にすごく力を発揮します。

C# の DB 接続関係が少し遅い問題のボトルネック解消

C# AoT によってアプリの起動時間は C 等のネイティブ系と同じ速度になりました。
一方で DB 速度がイマイチなのが気になります。
結論としては DB 接続に localhost を指定するとグローバルで探しに行くのが時間がかかる原因でした。IP を直に指定すると解消します。

Lang Hello World! DB Access
C 400 ms -
Rust 400 ms 400 ms
C# AoT 400 ms 600 ms ← 200 ms くらい遅い
C# JIT 800 ms 1000 ms JIT は少し遅い
C# AoT 改善版 400 ms 400 ms

(https ハンドシェクの時間を含まない)

ライブラリの問題かと思い MySqlConnector を見直してみました。

MySqlSharp が良さそうです。しかしながら解説 https://neue.cc/2017/08/07_556.html を見る限り、速度的にはあまり変わらないとあります。

検証の結果 DB 接続に localhost 文字列を指定するとグローバルで探しに行くため、時間がかかるのが原因でした。

var client = new TcpClient(AddressFamily.InterNetwork) {
    ReceiveTimeout = 99999,
    SendTimeout = 99999
};
if (server == "localhost")
    client.Connect(IPAddress.Loopback, port);
else
    client.Connect(server, port);

これを修正したところ Rust に比肩する性能が出ました。.NET が遅い、なんてことにならずに済みそうです。やったね。


  ┃   ┏━┃  ((;;;;゜;;:::::(;;:  ∧__,∧ '';:;;;):;:)):).) .     ┃┃ 
━┏┛ ┏━┃ ━(((; ;;:: ;:::;;⊂(`・ω・´)  ;:;;;,,))..).)━━┛     ┃┃ 
━┏┛ ┛  ┃    ((;;;:;;;:,,,." ヽ ⊂ ) ;:;;))):..,),)).:)          ┛┛ 
  ┛       ┛   ("((;:;;;(;::  (⌒) |. .どどどどど・・・                ┛┛ 
                         三 `J 

                      (.NET でパフォーマンスが出て歓喜する様子)

そのうち DB ドライバも書いてみたいですね(少し書き始めている)。

WinForms アプリの AoT

WinForms は AoT ビルドしようとするとコンパイルエラーになりますが、↓で回避できます。

<PropertyGroup>
    <_SuppressWinFormsTrimError>true</_SuppressWinFormsTrimError>
</PropertyGroup>
  • 出力アプリのサイズは最小構成で 18MB くらいです
  • ファイルサイズは大きい気もしますが、.NET の自己完結型出力だと 100MB くらいなのでかなり圧縮されています
  • リフレクション系の機能にタッチするとアプリが落ちます
    • 具体的には DataGridView.DataSource にタッチすると落ちます
    • その他の型の DataSource も同様に落ちます
  • 図らずとも難読化される利点があります

かんたん AoT 出力

https://qiita.com/spc_ksudoh/items/dc579d694da529f0d932 の記事がとても参考になります。
.NET preview6 の新機能で、単一のコンソールアプリ .cs ファイルを Aot 出力できるようになりました。

標準だと出力先は Tmp フォルダになるようですが、出力先を指定することもできます。

dotnet publish Program.cs -o publish

publish フォルダに Program.exe が出力されます。

AoT でアセンブリ取得しようとすると落ちる問題

AoT でリフレクションを使ったアセンブリの取得をするとアプリが落ちます。

// 現在のメソッドを呼び出しているアセンブリを取得
Assembly.GetCallingAssembly();

// 実行中のアプリのエントリポイントがあるアセンブリを取得
Assembly.GetEntryAssembly();

// このコードを実行しているアセンブリを取得
Assembly.GetExecutingAssembly();

↑ これらはランタイム版の .NET でも x64 環境で呼び出すとなんか落ちることがあるんですよね・・・

アセンブリ型を使う場面はあまりないですが、アセンブリの埋め込みリソースを取得する場合に使います。以下のように書くのがよさげです。

using var stream = typeof(MyType).Assembly.GetManifestResourceStream("Namespace.ResourceName.txt");

typeof(T) 演算子は AoT でも安全です。AoT の場合はコンパイル時に型が決定するため、多分 this.GetType() よりいいでしょう。

.NET10 Preview 7

.NET10 Preview7 が利用可能になりました。
今回は C# 機能追加は特になさそうです。時期的にリリースに向けて安定性向上とかに注力しているのでしょう。

例年のスケジュールですと

  • 8月:Preview7
  • 9月:RC1
  • 10月:RC2
  • 11月:.NET 10 正式リリース(LTS)

以前のバージョンのサポート状況はこんな感じです。.NET 8 のサポート期限が意外と短いです。

バージョン 元のリリース日 リリースの種類 サポート終了
.NET 9 2024年11月12日 STS 2026年5月12日
.NET 8 2023年11月14日 LTS 2026年11月10日

おわりに

AoT は興味深い分野で、試行錯誤中です。既存のコードは意外とリフレクションを使った部分があり、手を加えないと動かないことが多いです。

DirectX 系のアプリも AoT できることを確認できたので、ゲームアプリのリリースも AoT でできそうな感触を得ました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?