Skip to content

Commit 6099297

Browse files
authored
[msbuild] Sort inputs when doing aot compilation and native compilation. (#22755)
Sort inputs when doing AOT compilation and native code compilation, so that we start by processing the input that takes the longest to process. This helps maximizing usage of parallel resources, because there's a smaller chance we'll be left at the end working on a single long-running task. Some tentative timings from compiling monotouch-test locally, it shows a few seconds improvement (which percentage-wise can be significant). | Task | Before | After | | ----------------------- | ------ | ----- | | Native code compilation | ~25s | ~22s | | AOT compilation | ~23s | ~22s |
1 parent eaccc66 commit 6099297

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

msbuild/Xamarin.MacDev.Tasks/Tasks/AOTCompile.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,25 @@ public override bool Execute ()
272272
if (dedupAssembly is not null && !assembliesToAOT.Contains (dedupAssembly))
273273
assembliesToAOT.Add (dedupAssembly);
274274

275+
// Sort the assemblies:
276+
// We want to start with the assemblies that takes the longest to compile, because
277+
// that will make most efficient use of parallel resources.
278+
// 1. The dedup assembly is typically quite big, so do that first.
279+
// 2. Sort the rest of the assemblies by size, in decreasing order.
280+
var sortedAssembliesToAOT = assembliesToAOT
281+
// Compute the data we need to sort. We set file length to long.MaxValue if it's a dedup assembly so that it sorts where we want it
282+
.Select (item => {
283+
var isDedup = Boolean.TryParse (item.GetMetadata ("IsDedupAssembly"), out var isDedupAssembly) && isDedupAssembly;
284+
return (Item: item, InputLength: isDedup ? long.MaxValue : new FileInfo (item.GetMetadata ("Input")).Length);
285+
})
286+
// Sort
287+
.OrderByDescending (x => x.InputLength);
288+
foreach (var item in sortedAssembliesToAOT) {
289+
Log.LogMessage (MessageImportance.Low, $"Ahead-of-time compiling with sort order {item.InputLength}: {item.Item.GetMetadata ("Input")}");
290+
}
291+
292+
assembliesToAOT = sortedAssembliesToAOT.Select (v => v.Item).ToList ();
293+
275294
Directory.CreateDirectory (OutputDirectory);
276295

277296
var aotAssemblyFiles = new List<ITaskItem> ();
@@ -290,6 +309,7 @@ public override bool Execute ()
290309
var aotAssemblyItem = new TaskItem (aotAssembly);
291310
aotAssemblyItem.SetMetadata ("Arguments", "-Xlinker -rpath -Xlinker @executable_path/ -Qunused-arguments -x assembler -D DEBUG");
292311
aotAssemblyItem.SetMetadata ("Arch", arch);
312+
aotAssemblyItem.SetMetadata ("IsDedupAssembly", asm.GetMetadata ("IsDedupAssembly"));
293313
aotAssemblyFiles.Add (aotAssemblyItem);
294314

295315
var arguments = new List<string> ();

msbuild/Xamarin.MacDev.Tasks/Tasks/CompileNativeCode.cs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.IO;
4+
using System.Linq;
45
using System.Threading.Tasks;
56

67
using Microsoft.Build.Framework;
@@ -48,10 +49,29 @@ public override bool Execute ()
4849
return new TaskRunner (SessionId, BuildEngine4).RunAsync (this).Result;
4950
}
5051

51-
var processes = new Task<Execution> [CompileInfo.Length];
52+
// Sort the list of inputs to compile:
53+
// We want to start with the input that takes the longest to compile, because
54+
// that will make most efficient use of parallel resources.
55+
// 1. The dedup assembly is typically quite big, so do that first.
56+
// 2. Sort the rest of the inputs by size, in decreasing order.
57+
var sortedCompileInfo = CompileInfo
58+
// Compute the data we need to sort. We set file length to long.MaxValue if it's a dedup assembly so that it sorts where we want it
59+
.Select (item => {
60+
var isDedup = Boolean.TryParse (item.GetMetadata ("IsDedupAssembly"), out var isDedupAssembly) && isDedupAssembly;
61+
return (Item: item, InputLength: isDedup ? long.MaxValue : new FileInfo (item.ItemSpec).Length);
62+
})
63+
// Sort
64+
.OrderByDescending (x => x.InputLength);
65+
foreach (var item in sortedCompileInfo) {
66+
Log.LogMessage (MessageImportance.Low, $"Compiling with sort order {item.InputLength}: {item.Item.ItemSpec}");
67+
}
68+
69+
var compileInfo = sortedCompileInfo.Select (v => v.Item).ToArray ();
70+
71+
var processes = new Task<Execution> [compileInfo.Length];
5272

53-
for (var i = 0; i < CompileInfo.Length; i++) {
54-
var info = CompileInfo [i];
73+
for (var i = 0; i < compileInfo.Length; i++) {
74+
var info = compileInfo [i];
5575
var src = Path.GetFullPath (info.ItemSpec);
5676
var arguments = new List<string> ();
5777

0 commit comments

Comments
 (0)