Skip to content

Commit 339c6a1

Browse files
authored
[XABT] Use SortedSets in JCWGenerator.EnsureIdenticalCollections for better performance. (#9208)
`JCWGenerator.EnsureIdenticalCollections` ensures that every architecture being built contains the same Java derived types. Because this includes `Mono.Android.dll`, even the `dotnet new android` template has ~8500 Java types found. The current implementation uses nested loops and is O(N²). By first sorting the items into `SortedSet` types and then using `SetEquals` we can significantly speed up this operation. Fresh `dotnet build` of Android template (defaults to 4 architectures), `EnsureIdenticalCollections` takes: | | | | - | - | | `main` | 3081 ms | | PR | 29 ms |
1 parent 654440b commit 339c6a1

File tree

1 file changed

+9
-28
lines changed

1 file changed

+9
-28
lines changed

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

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -245,39 +245,20 @@ static void EnsureIdenticalCollections (TaskLoggingHelper logger, NativeCodeGenS
245245
{
246246
logger.LogDebugMessage ($"Ensuring Java type collection in architecture '{state.TargetArch}' matches the one in architecture '{templateState.TargetArch}'");
247247

248-
List<TypeDefinition> templateTypes = templateState.AllJavaTypes;
249-
List<TypeDefinition> types = state.AllJavaTypes;
248+
var templateSet = new SortedSet<string> (templateState.AllJavaTypes.Select (t => t.FullName), StringComparer.Ordinal);
249+
var typesSet = new SortedSet<string> (state.AllJavaTypes.Select (t => t.FullName), StringComparer.Ordinal);
250250

251-
if (types.Count != templateTypes.Count) {
252-
throw new InvalidOperationException ($"Internal error: architecture '{state.TargetArch}' has a different number of types ({types.Count}) than the template architecture '{templateState.TargetArch}' ({templateTypes.Count})");
251+
if (typesSet.Count != templateSet.Count) {
252+
throw new InvalidOperationException ($"Internal error: architecture '{state.TargetArch}' has a different number of types ({typesSet.Count}) than the template architecture '{templateState.TargetArch}' ({templateSet.Count})");
253253
}
254254

255-
var matchedTemplateTypes = new HashSet<TypeDefinition> ();
256-
var mismatchedTypes = new List<TypeDefinition> ();
257-
258-
foreach (TypeDefinition type in types) {
259-
TypeDefinition? matchedType = null;
260-
261-
foreach (TypeDefinition templateType in templateTypes) {
262-
if (matchedTemplateTypes.Contains (templateType) || !CheckWhetherTypesMatch (templateType, type)) {
263-
continue;
264-
}
265-
266-
matchedTemplateTypes.Add (templateType);
267-
matchedType = templateType;
268-
break;
269-
}
255+
if (!typesSet.SetEquals (templateSet)) {
256+
logger.LogError ($"Architecture '{state.TargetArch}' has Java types which have no counterparts in template architecture '{templateState.TargetArch}':");
270257

271-
if (matchedType == null) {
272-
mismatchedTypes.Add (type);
273-
}
274-
}
258+
typesSet.ExceptWith (templateSet);
275259

276-
if (mismatchedTypes.Count > 0) {
277-
logger.LogError ($"Architecture '{state.TargetArch}' has Java types which have no counterparts in template architecture '{templateState.TargetArch}':");
278-
foreach (TypeDefinition td in mismatchedTypes) {
279-
logger.LogError ($" {td.FullName}");
280-
}
260+
foreach (var type in typesSet)
261+
logger.LogError ($" {type}");
281262
}
282263
}
283264

0 commit comments

Comments
 (0)