NetWasmという実験的なプロジェクトは、条件を厳密に定めたテストにおいて、そのC#ツールチェーンがRustよりも小さい単体のWebAssemblyコンポーネントを生成したとしている。これは、ランタイムの設計とビルド設定がバイナリのサイズにどれほど影響し得るかを浮き彫りにする結果だ。同プロジェクトの報告では、NetWasmの出力は47,895バイトで、Rust 1.95.0は53,635バイトだった。

両方の生成物は同じく42を出力する処理を実行し、WASI Preview 2コンポーネントを対象とした。NetWasmの出力には、ランタイムと正確な参照追跡を行うガベージコレクタが含まれていた。Rustのビルドには、サイズ最適化、リンク時最適化、単一のコード生成ユニット、パニック時の即時終了、シンボルの削除など、文書化されたサイズ重視の設定が使われた。この条件で、NetWasmの生成物は圧縮前で10.7%、Brotliのレベル11で圧縮した場合は19.5%小さかったと報告されている。

リポジトリでは、この結論が適用できる範囲を明確に限定している。これは一つの処理とプロファイルに関する結果であり、一般にC#がRustより小さいWebAssemblyプログラムを作るという証明ではない。より踏み込んだ代替手法を用いれば、機能を変えることと引き換えに、どちらもさらに小さくできる可能性がある。Rustではno_stdを使える一方、C#では標準ライブラリの多くとガベージコレクションを省く最小限のライブラリを組み合わせられる。この比較が対象とするのは、選択したランタイムの範囲内で通常サポートされるビルドだ。

NetWasmは、デスクトップ向けの.NETやMonoをブラウザやWASI環境に持ち込むのとは異なる方法を採る。まずRoslynが共通中間言語(CIL)を生成し、続いてNetWasmが到達可能なコードをWebAssemblyにコンパイルして、ジェネリクスを特殊化し、必要なランタイム支援機能だけをリンクする。通常の出力は自己完結型の.NETプログラムだが、実行にはWasmtimeなどの互換性のあるWebAssemblyホストが依然として必要になる。

このツールチェーンは、標準のコンパイラ処理工程にBinaryenのwasm-optも組み込んでいる。同プロジェクトによると、同じツールをRustのWASI Preview 2コンポーネントに直接適用するには、そのコアモジュールを抽出してからコンポーネントを再構築する必要があるため、この追加の手動手順は比較に含めなかったという。NetWasmの数値は、標準のリリース用発行手順によるものだ。

NetWasmはまだバージョン1.0に達しておらず、デスクトップ向け.NETより意図的に範囲を絞ったプロファイルをサポートしている。リポジトリには、マネージドスレッド、実行時のアセンブリ読み込み、動的機能、いくつかの汎用的なオペレーティングシステムAPIなど、重要な非対応項目が列挙されている。既存のNuGetパッケージが動作するのは、実際に到達するコードがサポート範囲に収まる場合に限られる。インターフェースや互換性がマイナーリリース間で変わる可能性もある。

したがって、このベンチマークは二つの言語への判定というより、設計上の選択を示す実例として読むのが適切だ。コンパイラが小型のランタイム、選択的なリンク、意図的に制約したプラットフォームを用いれば、C#でもネイティブなWebAssemblyに匹敵するサイズの出力を実現できることを示している。その優位性が続くかどうかは、アプリケーション、必要なAPI、最適化のルール、開発者が受け入れられる妥協点によって変わる。