You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[linker] shortcircuit to prevent string.Format calls
I was using the Mono profiler for our build, and I noticed:
Allocation summary
Bytes Count Average Type name
180765632 2142803 84 System.String
53218472 bytes from:
MonoDroid.Tuner.FixAbstractMethodsStep:FixAbstractMethods (Mono.Cecil.AssemblyDefinition)
MonoDroid.Tuner.FixAbstractMethodsStep:FixAbstractMethodsUnconditional (Mono.Cecil.AssemblyDefinition)
MonoDroid.Tuner.FixAbstractMethodsStep:FixAbstractMethods (Mono.Cecil.TypeDefinition)
MonoDroid.Tuner.FixAbstractMethodsStep:HaveSameSignature (Mono.Cecil.TypeReference,Mono.Cecil.MethodDefinition,Mono.Cecil.MethodDefinition)
(wrapper managed-to-native) string:FastAllocateString (int)
~53MB of string from this one method is a lot!
I found that one of these `string.Format` calls are running for almost
every method on every interface in every assembly:
(string.Format ("{0}.{1}", iface.FullName, iMethod.Name) != tMethod.Name) :
(string.Format ("{0}.{1}.{2}", iMethod.DeclaringType.DeclaringType, iface.Name, iMethod.Name) != tMethod.Name))
Even the simplest non-matching cases would call `string.Format`:
iMethod.Name == "Foo"
tMethod.Name == "Bar"
Since this if-statement is quite long, I refactored it into a new
`HaveSameMethodName` method to match the `HaveSameSignature` method.
I added a simple check that would skip the `string.Format` calls:
if (tMethod.Name.IndexOf (".", StringComparison.Ordinal) == -1)
return false;
If there is no ".", we don't need to append strings that would contain
one. There is no way the `==` would match in that case.
~~ Results ~~
An initial build of the Xamarin.Forms integration project on
Windows/.NET framework:
Before:
796 ms LinkAssembliesNoShrink 1 calls
After:
767 ms LinkAssembliesNoShrink 1 calls
The same project on macOS/Mono (slightly slower machine, too):
Before:
1341 ms LinkAssembliesNoShrink 1 calls
After:
1025 ms LinkAssembliesNoShrink 1 calls
String allocations are way better, too:
Before:
Allocation summary
Bytes Count Average Type name
180765632 2142803 84 System.String
After:
Allocation summary
Bytes Count Average Type name
127736832 1652070 77 System.String
Shows 53,028,800 bytes saved.
Before:
53218472 bytes from:
MonoDroid.Tuner.FixAbstractMethodsStep:FixAbstractMethods (Mono.Cecil.AssemblyDefinition)
MonoDroid.Tuner.FixAbstractMethodsStep:FixAbstractMethodsUnconditional (Mono.Cecil.AssemblyDefinition)
MonoDroid.Tuner.FixAbstractMethodsStep:FixAbstractMethods (Mono.Cecil.TypeDefinition)
MonoDroid.Tuner.FixAbstractMethodsStep:HaveSameSignature (Mono.Cecil.TypeReference,Mono.Cecil.MethodDefinition,Mono.Cecil.MethodDefinition)
After:
1933624 bytes from:
MonoDroid.Tuner.FixAbstractMethodsStep:FixAbstractMethodsUnconditional (Mono.Cecil.AssemblyDefinition)
MonoDroid.Tuner.FixAbstractMethodsStep:FixAbstractMethods (Mono.Cecil.TypeDefinition)
MonoDroid.Tuner.FixAbstractMethodsStep:HaveSameSignature (Mono.Cecil.TypeReference,Mono.Cecil.MethodDefinition,Mono.Cecil.MethodDefinition)
MonoDroid.Tuner.FixAbstractMethodsStep:HaveSameMethodName (Mono.Cecil.TypeReference,Mono.Cecil.MethodDefinition,Mono.Cecil.MethodDefinition)
Shows 51,284,848 bytes saved.
I don't know about the discrepancy between these two sets of numbers.
But I think this is roughly ~50MB less string allocations.
0 commit comments