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 대상을 지원합니다.
- 표준
dotnetCLI를 통해 빌드, 실행, 게시 및 테스트. - 브라우저 또는 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 앱이 아닌 콘솔 컴포넌트와의 비교이며, 전체 프레임워크 동등성이 아닙니다.
커뮤니티 피드백 하이라이트
"비교가 약간 불공평합니다. 벤치마크된 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에서 사용할 수 있으며 저장소에 문서화되어 있습니다.