Skip to content

Commit 8ab9d33

Browse files
[Java.Interop.Tools.TypeNameMappings] improve ToJniNameFromAttributesForAndroid (#1064)
Reviewing `dotnet-trace` output: dotnet trace collect --format speedscope -- C:\src\xamarin-android\bin\Release\dotnet\dotnet.exe build -bl --no-restore bar.csproj On a `dotnet new maui` application, I noticed: 79.40ms java.interop.tools.javacallablewrappers!Java.Interop.Tools.TypeNameMappings.JavaNativeTypeManager.ToJniNameFromAttribute This method just appears to be called *a lot*, and so things I changed: * Check `type.HasCustomAttributes`, `attributeType.HasInterfaces`, and `attr.HasProperties` where appropriate. * Unroll the `System.Linq` usage one level, and use plain `foreach` * Create a `IsIJniNameProviderAttribute` method that checks against a list of known attribute types as a "fast path". * The "slow path" can continue to check for the `IJniNameProviderAttribute` interface Other changes: * Delete `#region`! After these changes, I get: 51.64ms (1.2%) 0.13ns (<0.01%) java.interop.tools.javacallablewrappers!Java.Interop.Tools.TypeNameMappings.JavaNativeTypeManager.ToJniNameFromAttribute This should save ~27ms on incremental builds of the `dotnet new maui` project template and likely even more on larger projects.
1 parent 09f8da2 commit 8ab9d33

File tree

1 file changed

+32
-10
lines changed

1 file changed

+32
-10
lines changed

src/Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings/JavaNativeTypeManager.cs

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -567,25 +567,47 @@ public static string ToJniName (TypeDefinition type, IMetadataResolver? resolver
567567

568568
static string? ToJniNameFromAttributesForAndroid (TypeDefinition type, IMetadataResolver? resolver)
569569
{
570-
#region CustomAttribute alternate name support
571-
var attrs = type.CustomAttributes.Where (a => Resolve (resolver, a.AttributeType).Interfaces.Any (it => it.InterfaceType.FullName == typeof (IJniNameProviderAttribute).FullName));
572-
return attrs.Select (attr => {
573-
var ap = attr.Properties.FirstOrDefault (p => p.Name == "Name");
570+
if (!type.HasCustomAttributes)
571+
return null;
572+
foreach (var attr in type.CustomAttributes) {
573+
if (!IsIJniNameProviderAttribute (attr, resolver))
574+
continue;
575+
var ap = attr.HasProperties ? attr.Properties.FirstOrDefault (p => p.Name == "Name") : default;
574576
string? name = null;
575577
if (ap.Name == null) {
576578
var ca = attr.ConstructorArguments.FirstOrDefault ();
577579
if (ca.Type == null || ca.Type.FullName != "System.String")
578-
return null;
580+
continue;
579581
name = (string) ca.Value;
580582
} else
581583
name = (string) ap.Argument.Value;
582584
if (!string.IsNullOrEmpty (name))
583585
return name.Replace ('.', '/');
584-
else
585-
return null;
586-
})
587-
.FirstOrDefault (s => s != null);
588-
#endregion
586+
}
587+
return null;
588+
}
589+
590+
static readonly HashSet<string> KnownIJniNameProviders = new HashSet<string> (StringComparer.Ordinal) {
591+
"Android.App.ActivityAttribute",
592+
"Android.App.ApplicationAttribute",
593+
"Android.App.InstrumentationAttribute",
594+
"Android.App.ServiceAttribute",
595+
"Android.Content.BroadcastReceiverAttribute",
596+
"Android.Content.ContentProviderAttribute",
597+
"Android.Runtime.RegisterAttribute",
598+
};
599+
600+
static bool IsIJniNameProviderAttribute (CustomAttribute attr, IMetadataResolver? resolver)
601+
{
602+
// Fast path for a list of known IJniNameProviderAttribute implementations
603+
if (KnownIJniNameProviders.Contains (attr.AttributeType.FullName))
604+
return true;
605+
606+
// Slow path resolves the type, looking for IJniNameProviderAttribute
607+
var attributeType = Resolve (resolver, attr.AttributeType);
608+
if (!attributeType.HasInterfaces)
609+
return false;
610+
return attributeType.Interfaces.Any (it => it.InterfaceType.FullName == typeof (IJniNameProviderAttribute).FullName);
589611
}
590612

591613
static TypeDefinition Resolve (IMetadataResolver? resolver, TypeReference typeReference) =>

0 commit comments

Comments
 (0)