crates/bindings-csharp/NATIVEAOT-LLVM.md
This guide provides instructions for enabling NativeAOT-LLVM compilation for C# SpacetimeDB modules, which can provide performance improvements.
NativeAOT-LLVM compiles C# modules to native WebAssembly (WASM) instead of using the Mono runtime.
[!WARNING] This is currently only supported for Windows server modules and is experimental.
upstream/emscripten/emcc.bat)PATH (recommended: version_116)The Emscripten SDK is required for NativeAOT-LLVM compilation:
Download and extract the Emscripten SDK from https://github.com/emscripten-core/emsdk
D:\Tools\emsdkSet environment variable (optional - the CLI will detect it automatically):
$env:EMSDK="D:\Tools\emsdk"
Binaryen provides wasm-opt for WASM optimization (recommended for performance):
Download Binaryen https://github.com/WebAssembly/binaryen/releases/tag/version_116 for Windows
Extract to e.g. D:\Tools\binaryen
Add D:\Tools\binaryen\bin to PATH
To temporarily add to your current PowerShell session:
$env:PATH += ";D:\Tools\binaryen\bin"
Verify:
wasm-opt --version
When creating a new C# project, use the --native-aot flag:
spacetime init --lang csharp --native-aot my-native-aot-project
This automatically:
spacetime.json with "native-aot": trueUpdate spacetime.json
Add "native-aot": true to your spacetime.json:
{
"module": "your-module-name",
"native-aot": true
}
Note: Once spacetime.json has "native-aot": true, you can simply run spacetime publish without the --native-aot flag. The CLI will automatically detect the configuration and use NativeAOT compilation.
Ensure NuGet feed is configured
NativeAOT-LLVM packages come from dotnet-experimental. Add to NuGet.Config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="dotnet-experimental" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>
Add NativeAOT package references
Add this ItemGroup to your .csproj:
<ItemGroup Condition="'$(EXPERIMENTAL_WASM_AOT)' == '1'">
<PackageReference Include="Microsoft.NET.ILLink.Tasks" Version="8.0.0-*" Condition="'$(ILLinkTargetsPath)' == ''" />
<PackageReference Include="Microsoft.DotNet.ILCompiler.LLVM" Version="8.0.0-*" />
<PackageReference Include="runtime.$(NETCoreSdkPortableRuntimeIdentifier).Microsoft.DotNet.ILCompiler.LLVM" Version="8.0.0-*" />
</ItemGroup>
Your complete .csproj should look like:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>wasi-wasm</RuntimeIdentifier>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SpacetimeDB.Runtime" Version="2.0.*" />
</ItemGroup>
<ItemGroup Condition="'$(EXPERIMENTAL_WASM_AOT)' == '1'">
<PackageReference Include="Microsoft.NET.ILLink.Tasks" Version="8.0.0-*" Condition="'$(ILLinkTargetsPath)' == ''" />
<PackageReference Include="Microsoft.DotNet.ILCompiler.LLVM" Version="8.0.0-*" />
<PackageReference Include="runtime.$(NETCoreSdkPortableRuntimeIdentifier).Microsoft.DotNet.ILCompiler.LLVM" Version="8.0.0-*" />
</ItemGroup>
</Project>
After completing either the Creating a New NativeAOT Project or Converting an Existing Project steps above, you can publish your module normally:
# From your project directory
spacetime publish your-database-name
If you have "native-aot": true in your spacetime.json, the CLI will automatically detect this and use NativeAOT compilation. Alternatively, you can use:
spacetime publish --native-aot your-database-name
The CLI will display "Using NativeAOT-LLVM compilation (experimental)" when NativeAOT is enabled.
If you have package source mapping enabled in NuGet.Config, add mappings for the LLVM packages:
<packageSourceMapping>
<packageSource key="bsatn-runtime">
<package pattern="SpacetimeDB.BSATN.Runtime" />
</packageSource>
<packageSource key="SpacetimeDB.Runtime">
<package pattern="SpacetimeDB.Runtime" />
</packageSource>
<packageSource key="dotnet-experimental">
<package pattern="Microsoft.DotNet.ILCompiler.LLVM" />
<package pattern="runtime.*" />
</packageSource>
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
</packageSourceMapping>
If the CLI cannot install the wasi-experimental workload automatically, install it manually:
dotnet workload install wasi-experimental
You may see a NU1504 warning about duplicate PackageReference items. This is expected and non-blocking.
If you see errors like "Code generation failed for method", ensure:
SpacetimeDB.Runtime version 2.0.4 or newer.csprojdotnet-experimental feed is configured in NuGet.Config