Skip to content

Commit 728e4ea

Browse files
[Xamarin.Android.Build.Tasks] delay ToJniName calls in ManifestDocument (#7653)
Reviewing `dotnet trace` output for a `dotnet new maui` app: dotnet trace collect --format speedscope -- .\bin\Release\dotnet\dotnet.exe build -bl --no-restore foo.csproj 8.6% of the time in `<GenerateJavaStubs/>` is spent in: 93.81ms xamarin.android.build.tasks!Xamarin.Android.Tasks.ManifestDocument.Merge(...) Drilling down further, a lot of time is spent in: 26.91ms java.interop.tools.javacallablewrappers!Java.Interop.Tools.TypeNameMappings.JavaNativeTypeManager.ToJniName(...) 4.03ms java.interop.tools.javacallablewrappers!Java.Interop.Tools.TypeNameMappings.JavaNativeTypeManager.ToCompatJniName(...) It looks like we call this code for *every* Java.Lang.Object subclass: var name = JavaNativeTypeManager.ToJniName (t, cache).Replace ('/', '.'); var compatName = JavaNativeTypeManager.ToCompatJniName (t, cache).Replace ('/', '.'); if (((string) app.Attribute (attName)) == compatName) { app.SetAttributeValue (attName, name); } It looks like this code was originally here to solve a problem with `Android.App.Application` classes that are missing an `[Application]` attribute: xamarin/monodroid@2a668b7 To improve this: 1. First check if we are a `Android.App.Application`, apply the above fixup and `continue`. 2. Find out if we are other types of interesting subclasses, where a `generator` is needed. `continue` otherwise. 3. Lastly, compute `name` & `compatName`. We are no longer doing this work for every type. After these changes, I instead get: 72.84ms xamarin.android.build.tasks!Xamarin.Android.Tasks.ManifestDocument.Merge(...) This saves about ~21ms on incremental builds of `dotnet new maui` projects.
1 parent 0a58977 commit 728e4ea

File tree

1 file changed

+12
-4
lines changed

1 file changed

+12
-4
lines changed

src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -336,17 +336,20 @@ public IList<string> Merge (TaskLoggingHelper log, TypeDefinitionCache cache, Li
336336
if (PackageName == null)
337337
PackageName = t.Namespace;
338338

339-
var name = JavaNativeTypeManager.ToJniName (t, cache).Replace ('/', '.');
340-
var compatName = JavaNativeTypeManager.ToCompatJniName (t, cache).Replace ('/', '.');
341-
if (((string) app.Attribute (attName)) == compatName) {
342-
app.SetAttributeValue (attName, name);
339+
if (t.IsSubclassOf ("Android.App.Application", cache)) {
340+
(string name, string compatName) = GetNames (t, cache);
341+
if (((string) app.Attribute (attName)) == compatName) {
342+
app.SetAttributeValue (attName, name);
343+
}
344+
continue;
343345
}
344346

345347
Func<TypeDefinition, string, int, XElement> generator = GetGenerator (t, cache);
346348
if (generator == null)
347349
continue;
348350

349351
try {
352+
(string name, string compatName) = GetNames (t, cache);
350353
// activity not present: create a launcher for it IFF it has attribute
351354
if (!existingTypes.Contains (name) && !existingTypes.Contains (compatName)) {
352355
XElement fromCode = generator (t, name, targetSdkVersionValue);
@@ -481,6 +484,11 @@ SequencePoint FindSource (IEnumerable<MethodDefinition> methods)
481484
}
482485
}
483486

487+
(string name, string compatName) GetNames(TypeDefinition type, TypeDefinitionCache cache) => (
488+
JavaNativeTypeManager.ToJniName (type, cache).Replace ('/', '.'),
489+
JavaNativeTypeManager.ToCompatJniName (type, cache).Replace ('/', '.')
490+
);
491+
484492
// FIXME: our manifest merger is hacky.
485493
// To support complete manifest merger, we will have to implement fairly complicated one, described at
486494
// http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger

0 commit comments

Comments
 (0)