Description
On Apple mobile platforms, non-user assemblies are compiled into an R2R composite image, while their IL bodies are not stripped. In general, R2R is used for optimization, and when tiered compilation is enabled, the original IL method bodies must be preserved.
On Apple mobile, R2R is the default compilation engine for non-user assemblies. This means the IL bodies are not required for execution. If they were stripped, this would yield an estimated ~40% size reduction per dll in a MAUI template app bundle.
To validate this, I implemented a simple IL stripping mechanism in crossgen2 by emitting a minimal method body (tiny header + ret):
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
if (relocsOnly)
{
return new ObjectData(
data: Array.Empty<byte>(),
relocs: Array.Empty<Relocation>(),
alignment: 1,
definedSymbols: new ISymbolDefinitionNode[] { this });
}
// Emit a minimal stub method body instead of the original IL.
if (factory.OptimizationFlags.StripILBodies && !ShouldPreserveILBody())
{
return new ObjectData(new byte[] { 0x06, 0x2A }, Array.Empty<Relocation>(), 4, new ISymbolDefinitionNode[] { this });
}
var rva = _method.MetadataReader.GetMethodDefinition(_method.Handle).RelativeVirtualAddress;
var reader = _method.Module.PEReader.GetSectionData(rva).GetReader();
int size = MethodBodyBlock.Create(reader).Size;
return new ObjectData(reader.ReadBytes(size), Array.Empty<Relocation>(), 4, new ISymbolDefinitionNode[] { this });
}
However, it appears that MAUI initialization code relies on IL bodies. This leads to several failures, including:
- Failure in xamarin_bridge_call_runtime_initialize
- Failure in xamarin_find_assembly (the managed function find_assembly could not be loaded)
- Failures in xamarin_print_all_exceptions_wrapper
A workaround was to strip IL only for void methods from third-party NuGet packages (excluding SDK assemblies). With this approach, the size reduction reached only ~20% of the maximum.
To fully enable IL stripping safely, we need a reliable set of rules to identify all methods that are used during MAUI startup.
ips-1.txt
ips-2.txt
ips-3.txt
Description
On Apple mobile platforms, non-user assemblies are compiled into an R2R composite image, while their IL bodies are not stripped. In general, R2R is used for optimization, and when tiered compilation is enabled, the original IL method bodies must be preserved.
On Apple mobile, R2R is the default compilation engine for non-user assemblies. This means the IL bodies are not required for execution. If they were stripped, this would yield an estimated ~40% size reduction per dll in a MAUI template app bundle.
To validate this, I implemented a simple IL stripping mechanism in crossgen2 by emitting a minimal method body (tiny header + ret):
However, it appears that MAUI initialization code relies on IL bodies. This leads to several failures, including:
A workaround was to strip IL only for void methods from third-party NuGet packages (excluding SDK assemblies). With this approach, the size reduction reached only ~20% of the maximum.
To fully enable IL stripping safely, we need a reliable set of rules to identify all methods that are used during MAUI startup.
ips-1.txt
ips-2.txt
ips-3.txt