Skip to content

Commit 96a73e6

Browse files
authored
[CoreCLR] Remove unused marshal methods code (#10180)
Our build process targetting CoreCLR generated marshal methods code that is only used by our MonoVM runtime. The native code included marshal methods and class names, as well as assembly image cache which is not supported on CoreCLR. All of the above data were stored as pointers in the resulting `libxamarin-app.so`, each pointer being a relocation that has to be fixed up by the system dynamic linker at application load time. The more relocations exist across the `.so` file, the more of it the linker has to actually read into memory (instead of just mmapping it and lazily loading whenever/if the code/data in that section is used). This PR removes all of that code from the CoreCLR version of `libxamarin-app.so`, together with a number of native structs supporting the data. Testing the changes on a `dotnet new maui -sc` application, we can see the following savings: * Number of relocations in `libxamarin-app.so` drops from 903 to 394 entries * `libxamarin-app.so` size drops from: * arm64: 443648 to 368832 bytes (16.9%) * x64: 438856 to 360464 bytes (17.9%) Testing the above MAUI app performance on Pixel 8, we can also see a tiny startup time decrease by 0.71%. On slower devices and with bigger applications the startup performance improvement will be bigger (the slower the device's storage, the bigger time savings)
1 parent c7ec0ac commit 96a73e6

File tree

8 files changed

+375
-380
lines changed

8 files changed

+375
-380
lines changed

src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeMarshalMethodSources.cs

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,20 @@ public class GenerateNativeMarshalMethodSources : AndroidTask
2929
[Required]
3030
public ITaskItem [] ResolvedAssemblies { get; set; } = [];
3131

32+
[Required]
33+
public string AndroidRuntime { get; set; } = "";
34+
3235
public ITaskItem [] SatelliteAssemblies { get; set; } = [];
3336

3437
[Required]
3538
public string [] SupportedAbis { get; set; } = [];
3639

40+
AndroidRuntime androidRuntime;
41+
3742
public override bool RunTask ()
3843
{
3944
NativeCodeGenStateCollection? nativeCodeGenStates = null;
45+
androidRuntime = MonoAndroidHelper.ParseAndroidRuntime (AndroidRuntime);
4046

4147
if (EnableMarshalMethods) {
4248
// Retrieve the stored NativeCodeGenStateCollection (and remove it from the cache)
@@ -60,24 +66,11 @@ void Generate (NativeCodeGenStateCollection? nativeCodeGenStates, string abi)
6066
var marshalMethodsLlFilePath = $"{marshalMethodsBaseAsmFilePath}.ll";
6167
var (assemblyCount, uniqueAssemblyNames) = GetAssemblyCountAndUniqueNames ();
6268

63-
MarshalMethodsNativeAssemblyGenerator marshalMethodsAsmGen;
64-
65-
if (EnableMarshalMethods) {
66-
marshalMethodsAsmGen = new MarshalMethodsNativeAssemblyGenerator (
67-
Log,
68-
assemblyCount,
69-
uniqueAssemblyNames,
70-
EnsureCodeGenState (nativeCodeGenStates, targetArch),
71-
EnableManagedMarshalMethodsLookup
72-
);
73-
} else {
74-
marshalMethodsAsmGen = new MarshalMethodsNativeAssemblyGenerator (
75-
Log,
76-
targetArch,
77-
assemblyCount,
78-
uniqueAssemblyNames
79-
);
80-
}
69+
MarshalMethodsNativeAssemblyGenerator marshalMethodsAsmGen = androidRuntime switch {
70+
Tasks.AndroidRuntime.MonoVM => MakeMonoGenerator (),
71+
Tasks.AndroidRuntime.CoreCLR => MakeCoreCLRGenerator (),
72+
_ => throw new NotSupportedException ($"Internal error: unsupported runtime type '{androidRuntime}'")
73+
};
8174

8275
var marshalMethodsModule = marshalMethodsAsmGen.Construct ();
8376
using var marshalMethodsWriter = MemoryStreamPool.Shared.CreateStreamWriter ();
@@ -88,6 +81,44 @@ void Generate (NativeCodeGenStateCollection? nativeCodeGenStates, string abi)
8881
marshalMethodsWriter.Flush ();
8982
Files.CopyIfStreamChanged (marshalMethodsWriter.BaseStream, marshalMethodsLlFilePath);
9083
}
84+
85+
MarshalMethodsNativeAssemblyGenerator MakeMonoGenerator ()
86+
{
87+
if (EnableMarshalMethods) {
88+
return new MarshalMethodsNativeAssemblyGeneratorMonoVM (
89+
Log,
90+
assemblyCount,
91+
uniqueAssemblyNames,
92+
EnsureCodeGenState (nativeCodeGenStates, targetArch),
93+
EnableManagedMarshalMethodsLookup
94+
);
95+
}
96+
97+
return new MarshalMethodsNativeAssemblyGeneratorMonoVM (
98+
Log,
99+
targetArch,
100+
assemblyCount,
101+
uniqueAssemblyNames
102+
);
103+
}
104+
105+
MarshalMethodsNativeAssemblyGenerator MakeCoreCLRGenerator ()
106+
{
107+
if (EnableMarshalMethods) {
108+
return new MarshalMethodsNativeAssemblyGeneratorCoreCLR (
109+
Log,
110+
uniqueAssemblyNames,
111+
EnsureCodeGenState (nativeCodeGenStates, targetArch),
112+
EnableManagedMarshalMethodsLookup
113+
);
114+
}
115+
116+
return new MarshalMethodsNativeAssemblyGeneratorCoreCLR (
117+
Log,
118+
targetArch,
119+
uniqueAssemblyNames
120+
);
121+
}
91122
}
92123

93124
(int assemblyCount, HashSet<string> uniqueAssemblyNames) GetAssemblyCountAndUniqueNames ()

0 commit comments

Comments
 (0)