PublishReadyToRun configuration for trimmed low-traffic workloads
0 reputation · 20 May 2023, 11:42 UTC
0 reputation · 20 May 2023, 11:42 UTC
Reducing cold-start latency in low-traffic environments often involves using ReadyToRun (R2R) compilation to minimize Just-In-Time (JIT) overhead during application initialization. This requires specifying a precise Runtime Identifier (RID) to ensure native code compatibility with the target host.
When combining PublishReadyToRun with trimming to minimize the deployment footprint, there is a potential conflict regarding reflection-based members. If the trimmer removes metadata that the pre-compiled native code expects to find at runtime, the application may encounter unexpected failures that are not present in standard JIT-compiled builds.
Given a .NET 6+ environment targeting a specific Linux distribution:
PublishReadyToRun and TrimMode=partial affect the stability of reflection-heavy libraries?35275 reputation · 20 May 2023, 22:46 UTC
With TrimMode=partial, only assemblies explicitly marked IsTrimmable are trimmed. Reflection-heavy libraries that are not marked keep their full metadata, so PublishReadyToRun stability risk is low for them. For opted-in assemblies, the trimmer runs before R2R compilation; any reflection-only member removed becomes missing metadata that the precompiled native code may reference at runtime, producing failures such as MissingMethodException.
On Linux, use the portable RID linux-x64 (or linux-arm64) rather than a distro-specific RID. Minor kernel updates preserve the user-space ABI, so R2R compatibility depends on the target glibc version and CPU architecture, not the kernel version. Distro-specific RIDs like ubuntu.22.04-x64 tie the binary to that distro's ABI and reduce portability.
These points reflect documented .NET 6+ trimming and R2R behavior:
linux-x64 images assume glibc; they will not run on musl-based distributions such as Alpine without a separate build.IsTrimmable. If it is not, leave it out of trimming concerns and focus on RID choice.DynamicDependency or preserve roots, and enable trim analysis warnings.dotnet publish \
-c Release \
-r linux-x64 \
--self-contained true \
-p:PublishReadyToRun=true \
-p:TrimMode=partial \
-p:PublishTrimmed=true
Confirm the target glibc version on the host (for example, ldd --version or getconf GNU_LIBC_VERSION), then run the application there. Enable trim analysis and confirm there are zero unresolved ILLink warnings for any assembly marked IsTrimmable. Finally, measure cold-start latency with and without R2R under simulated low-traffic conditions to confirm the trade-off is worthwhile.
Is the reflection-heavy library explicitly marked IsTrimmable? If yes, you need preservation attributes and a clean ILLink pass before shipping. If no, partial trim leaves it untouched, and the remaining decision is purely about RID portability and whether R2R's size/memory overhead is justified for your traffic pattern.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.