NetWasm 0.10.0, C#이 WebAssembly 크기에서 Rust를 능가할 수 있게 하다

C#이 이제 WebAssembly 크기에서 Rust를 능가

핵심 요약: NetWasm 0.10.0은 간단한 print(42) 프로그램에 대해 47,895바이트의 독립형 WASI 컴포넌트를 생성하며, 이는 Rust 1.95.0 크기 프로파일 바이너리(53,635B)보다 10.7% 작고, Brotli-11 압축 후에는 19.5% 더 작습니다.

원시 및 압축 크기 비교

결과: NetWasm의 Compact GC 빌드는 원시 47,895B, 압축 13,660B입니다. Rust의 크기 프로파일 빌드는 원시 53,635B, 압축 16,963B입니다.

툴체인 원시 Wasm Brotli-11 역할
NetWasm, Compact GC 47,895B 13,660B 내장 정밀 GC를 갖춘 WASI Preview 2 컴포넌트
Rust 1.95.0, 크기 프로파일 53,635B 16,963B 일치하는 WASI Preview 2 컴포넌트
Kotlin 2.4.0 wasmWasi 79,293B 22,655B Preview 1; 호스트가 GC 제공
TinyGo 0.39.0 93,043B 26,931B Preview 1; 사용자 정의 GC

두 바이너리 모두 기본 릴리스 설정으로 생성되며 수동 후처리가 없습니다. NetWasm의 컴파일러 파이프라인은 항상 Binaryen의 wasm-opt를 실행하지만, Rust 빌드에는 컴포넌트 형식이 재인코딩을 복잡하게 만들기 때문에 동등한 단계가 포함되지 않습니다.

방법론 참고 사항

  • Rust 빌드는 opt-level = "z", LTO, 단일 코드젠 유닛, panic = "abort", 그리고 심볼 제거를 사용합니다.
  • NetWasm의 크기에는 런타임과 정밀 Compact 가비지 컬렉터가 포함됩니다.
  • 벤치마크는 단일 print(42) 워크로드를 반영하며, 언어 전반의 크기 순위가 아닙니다.
  • 두 툴체인 모두 no_std(Rust) 또는 제로 라이브러리 접근(C#)으로 더 줄일 수 있지만, 이러한 구성은 대부분의 표준 라이브러리와 C#의 경우 가비지 컬렉터를 희생합니다.

정확한 소스, 버전, 설정 및 재현 단계

Mono AOT 대비 성능 우위

핵심 요약: NetWasm의 할당 및 GC 벤치마크는 동일한 C# 소스에서 컴파일되고 Wasmtime에서 실행되는 Mono AOT보다 26-40% 더 빠릅니다.

워크로드 NetWasm (Compact GC) Mono AOT (.NET 10) 속도 향상
전체 트랜잭션 43.9ms 59.1ms 26% 더 빠름
유지된 객체 그래프 8.8ms 14.2ms 38% 더 빠름
UI 변경 17.6ms 29.1ms 40% 더 빠름

측정은 Apple M1 Max에서 Wasmtime 49.0.3을 사용하여 15회 실행의 중앙값입니다. NetWasm은 처음 두 워크로드에서 데스크톱 .NET 11 JIT보다도 우수하지만, UI 변경에서는 JIT가 약간 더 빠릅니다. Native AOT는 전반적으로 가장 빠릅니다.

버전, 설정, 데스크톱 수치 및 재현

hello-world를 넘어선 기능 세트

핵심 요약: NetWasm은 완전한 기능을 갖춘 C# 15 애플리케이션, JavaScript interop, 정적 .a 아카이브, WIT 바인딩, 표현식 트리, HTTP/JSON/XML, 리플렉션 없는 DI, 그리고 wasm32 및 wasm64 대상을 지원합니다.

  • 표준 dotnet CLI를 통해 빌드, 실행, 게시 및 테스트.
  • 브라우저 또는 Web Worker용 타입이 지정된 JavaScript 모듈 내보내기.
  • 생성된 C ABI 마샬링으로 네이티브 .a 아카이브 링크.
  • WIT에서 C# 바인딩 생성 및 독립형 WASI Preview 2 컴포넌트 생성.
  • NetWasm용으로 패키지된 LINQ, HTTP, JSON, XML, Regex 및 DI 라이브러리 사용.
  • netwasm0.1 및 데스크톱 .NET용 이중 대상 라이브러리.

프로필은 의도적으로 데스크톱 .NET보다 작지만, 이미 완전한 애플리케이션, 휴대용 라이브러리, 테스트 프로젝트 및 브라우저 모듈을 지원합니다.

빠른 시작 가이드

핵심 요약: .NET 10+ SDK와 NetWasm 템플릿을 설치하면 1분 안에 42를 출력하는 자체 포함 C# 프로그램을 컴파일하고 실행할 수 있습니다.

# .NET SDK 10.0.303+ 설치 (또는 C# 15용 .NET 11)
# NetWasm 템플릿 설치

dotnet new install NetWasm.Templates

dotnet new netwasm-app -n HelloNetWasm
cd HelloNetWasm

dotnet restore

dotnet run               # 42 출력

dotnet publish -c Release -o publish/local

# WASI Preview 2 호스트로 실행 (예: Wasmtime)
wasmtime run publish/local/HelloNetWasm.wasm

게시된 컴포넌트는 .NET에 대해 자체 포함입니다. 런타임에는 WASI 호스트만 필요합니다. ".NET으로 빌드하고, .NET 없이 실행하세요."

NetWasm이 작게 유지되는 방법

핵심 요약: NetWasm은 도달 가능한 CIL을 직접 Wasm으로 컴파일하고, 폐쇄 세계 분석을 수행하며, 실제로 사용되는 런타임 기능만 링크하여 크기를 달성합니다.

  • 폐쇄 세계 컴파일: 도달할 수 없는 코드, 임포트 및 런타임 기능은 생략됩니다.
  • 축소된 플랫폼 계약: 휴대용 API만 제공되며 데스크톱 런타임 가정은 제외됩니다.
  • 광범위한 리플렉션 없음: dynamic, 런타임 어셈블리 로딩 및 일반적인 유형 검사와 같은 기능은 생략됩니다.
  • 생성된 경계: JSON, DI, WIT 및 네이티브 interop은 런타임 검색 대신 정적 계약을 사용합니다.
  • 선택적 데이터: 시간대 데이터, 풍부한 스택 추적 및 진단은 명시적으로 활성화된 경우에만 포함됩니다.
  • 단일 컬렉터: 선택된 GC 전략만 최종 바이너리에 링크됩니다.

이것은 목적에 맞게 제작된 .NET 플랫폼이지, Wasm 샌드박스에 강제로 넣은 축소된 데스크톱 런타임이 아닙니다.

할당 전략 및 크기 트레이드오프

핵심 요약: NetWasm은 각각 고유한 크기와 성능 특성을 가진 세 가지 가비지 컬렉터 전략을 제공합니다.

전략 최적 용도 원시 컴포넌트 Brotli-11
Compact (기본값) 작은 앱, 낮은 변경 UI 47,895B 13,660B
NetWasmGC 더 높은 할당 처리량 50,855B 15,053B
Bump 제한된 일회성 작업 43,864B 11,959B

프로젝트 파일에 <NetWasmGarbageCollector>를 추가하여 전략을 선택하십시오. 속성을 생략하면 기본값은 Compact입니다.

라이브러리 호환성 모델

핵심 요약: NetWasm 라이브러리는 netwasm0.1 및 데스크톱 프레임워크(예: net10.0)를 다중 대상으로 하여 동일한 소스가 Wasm과 기존 .NET 모두에서 실행될 수 있게 합니다.

# 두 플랫폼을 대상으로 하는 라이브러리 생성

dotnet new netwasm-lib -n MyLibrary

생성된 NuGet 패키지에는 두 런타임 모두에 대한 자산이 포함되어 있지만, NetWasm 프로필에 맞는 라이브러리만 수정 없이 사용할 수 있습니다.

기존 Blazor WebAssembly와의 비교

핵심 요약: 42를 출력하는 Blazor WebAssembly AOT 빌드는 약 12MiB(.NET 10) 또는 15MiB(.NET 11)를 차지하여 NetWasm보다 약 256-319배 더 큽니다.

빌드 압축되지 않은 Wasm NetWasm 대비 크기 배수
NetWasm, Compact GC 47,895B 1배
Blazor WebAssembly, .NET 10 12,276,684B 256배
Blazor WebAssembly, .NET 11 RC1 15,289,241B 319배

Blazor 수치에는 네이티브 런타임과 필수 어셈블리가 포함됩니다. NetWasm에는 런타임, GC 및 WASI 컴포넌트가 포함됩니다. 이 비교는 빈 UI Blazor 앱이 아닌 콘솔 컴포넌트와의 비교이며, 전체 프레임워크 동등성이 아닙니다.

정확한 Blazor 버전, 설정 및 재현

커뮤니티 피드백 하이라이트

"비교가 약간 불공평합니다. 벤치마크된 C# 코드는 다른 대상에는 없는 후처리도 거쳤습니다. ... Rust는 훨씬 더 낮출 수 있습니다." – @sondr3

"C#에는 백엔드에 딱 맞는 무언가가 있습니다... 좋은 도구, 현대적인 언어 기능, 훌륭한 디버깅 경험." – @CharlieDigital

"이것이 오픈 소스가 아니라는 점을 지적할 가치가 있습니다. 두 가지를 비교할 때 중요한 고려 사항이라면 (저에게는 그렇습니다)." – @Scaled

"이 비교는 약간 불공평합니다. WASM에는 C#이 사용할 수 있는 가비지 컬렉터가 포함되어 있는 반면 Rust는 모든 메모리 관리를 직접 수행하므로 당연히 더 클 수밖에 없습니다." – @weinzierl (나중에 게시물을 읽은 후 수정)

"그렇게 어렵지 않습니다... Rust wasm 바이너리는 엄청납니다. WASM 성능, 크기 및 메모리 사용량에 관심이 있다면 Zig가 훨씬 더 나은 후보입니다." – @jedisct1

이러한 의견은 벤치마크의 공정성, 오픈 소스 라이선스, 가비지 컬렉터 오버헤드의 관련성 등 주요 논쟁점을 보여줍니다.

현재 상태 및 로드맵

핵심 요약: NetWasm은 1.0 이전 버전입니다. 0.10.0 릴리스는 재구축된 가비지 컬렉터와 크기 중심 최적화를 도입했습니다. 향후 작업은 더 넓은 WASI Preview 2 지원, 선택적 세계화 데이터, 완전한 표현식 트리 지원, 안정적인 netwasm1.0 계약 및 프로덕션 진단을 목표로 합니다.

  • 0.10.0 하이라이트: 객체에 컬렉터 헤더 없음, 단일 할당 배열, Boehm 컬렉터 제거, 할당 집약적 프로그램의 더 빠른 실행, 시간대 데이터의 시작 시간 단축.
  • 1.0으로 가는 길: WASI Preview 2 API 표면 확장, 더 많은 .NET Standard 2.1 라이브러리 활성화, 플랫폼 및 런타임 계약 안정화, 증분 개발 루프 개선.

프로젝트는 기여에 열려 있습니다. 이슈 및 기능 요청을 환영합니다.

라이선스 모델

핵심 요약: NetWasm의 핵심 라이브러리는 MIT 라이선스입니다. 컴파일러와 도구는 개인, 교육, 오픈 소스 작업 및 소규모 조직(직원 250명 이하, 매출 1천만 달러 이하)에게 무료인 NetWasm Community License 1.0을 사용합니다. 이러한 한도를 초과하는 상업적 사용은 별도 계약이 필요합니다.

  • 런타임 컬렉터(Compact, NetWasmGC)는 Apache-2.0입니다.
  • 생성된 애플리케이션에는 활성화, 원격 측정 또는 기술적 강제가 내장되어 있지 않습니다.

패키지 및 생태계

  • 컴파일러 및 SDK: NetWasm.Compiler.Tasks, NetWasm.Sdk, NetWasm.Templates
  • 런타임: NetWasm.Runtime.Wasm32, NetWasm.Runtime.Wasm64
  • 호스팅: NetWasm.Hosting, NetWasm.Hosting.Build
  • 라이브러리 포트: NetWasm.Libraries 스위트, TUnit-NetWasm

모든 패키지는 NuGet에서 사용할 수 있으며 저장소에 문서화되어 있습니다.


Sources