Skip to content

Commit 9fc19a1

Browse files
[Mono] Add the capability of trimming IL code of individual methods (#86722)
* Add the capability of trimming individual methods * Fix build errors * Remove printf's * Add the option to use compiled-methods-outfile * Avoid trimming shared methods when they are still in use * Add parameter description * Add the option to trim compiled methods * Address review feedback * Add metadata MethodTokenFile to CompiledAssemblies * Add GUID checks and use metadata of assemblies * Create smaller functions and use hex value * Update src/tasks/AotCompilerTask/MonoAOTCompiler.cs Co-authored-by: Ankit Jain <[email protected]> * Move parameter validation code * Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain <[email protected]> * Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain <[email protected]> * Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain <[email protected]> * Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain <[email protected]> * Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain <[email protected]> * Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain <[email protected]> * Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain <[email protected]> * Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain <[email protected]> * Add more error handling * Provide a list of trimmed assemblies as output * Update src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs Co-authored-by: Ankit Jain <[email protected]> * Address coding style feedbacks * Fix var anmes * Delete trimmed assemblies after copy --------- Co-authored-by: Ankit Jain <[email protected]>
1 parent 3afe6bd commit 9fc19a1

File tree

5 files changed

+298
-8
lines changed

5 files changed

+298
-8
lines changed

src/mono/mono/mini/aot-compiler.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9828,8 +9828,9 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
98289828
mono_atomic_inc_i32 (&acfg->stats.ccount);
98299829

98309830
if (acfg->aot_opts.compiled_methods_outfile && acfg->compiled_methods_outfile != NULL) {
9831-
if (!mono_method_is_generic_impl (method) && method->token != 0)
9831+
if (!mono_method_is_generic_impl (method) && method->token != 0) {
98329832
fprintf (acfg->compiled_methods_outfile, "%x\n", method->token);
9833+
}
98339834
}
98349835
}
98359836

@@ -14832,6 +14833,10 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options)
1483214833
acfg->compiled_methods_outfile = fopen (acfg->aot_opts.compiled_methods_outfile, "w+");
1483314834
if (!acfg->compiled_methods_outfile)
1483414835
aot_printerrf (acfg, "Unable to open compiled-methods-outfile specified file %s\n", acfg->aot_opts.compiled_methods_outfile);
14836+
else {
14837+
fprintf(acfg->compiled_methods_outfile, "%s\n", ass->image->filename);
14838+
fprintf(acfg->compiled_methods_outfile, "%s\n", ass->image->guid);
14839+
}
1483514840
}
1483614841

1483714842
if (acfg->aot_opts.data_outfile) {

src/mono/sample/HelloWorld/HelloWorld.csproj

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
LibraryFormat="$(_AotLibraryFormat)"
2626
Assemblies="@(AotInputAssemblies)"
2727
OutputDir="$(PublishDir)"
28+
CollectCompiledMethods="$(StripILCode)"
29+
CompiledMethodsOutputDirectory="$(CompiledMethodsOutputDirectory)"
2830
IntermediateOutputPath="$(IntermediateOutputPath)"
2931
UseAotDataFile="$(UseAotDataFile)"
3032
CacheFilePath="$(IntermediateOutputPath)aot_compiler_cache.json"
@@ -35,4 +37,26 @@
3537
<Output TaskParameter="CompiledAssemblies" ItemName="BundleAssemblies" />
3638
</MonoAOTCompiler>
3739
</Target>
40+
41+
<UsingTask TaskName="ILStrip"
42+
AssemblyFile="$(MonoTargetsTasksAssemblyPath)" />
43+
44+
<Target Name="StripILCode" Condition="'$(StripILCode)' == 'true'" AfterTargets="AOTCompileApp">
45+
<PropertyGroup>
46+
<TrimIndividualMethods>true</TrimIndividualMethods>
47+
</PropertyGroup>
48+
49+
<ILStrip
50+
TrimIndividualMethods="$(TrimIndividualMethods)"
51+
Assemblies="@(BundleAssemblies)">
52+
<Output TaskParameter="TrimmedAssemblies" ItemName="TrimmedAssemblies" />
53+
</ILStrip>
54+
55+
<Copy
56+
SourceFiles="@(TrimmedAssemblies->Metadata('TrimmedAssemblyFileName'))"
57+
DestinationFiles="@(TrimmedAssemblies)"
58+
OverwriteReadOnlyFiles="true"
59+
/>
60+
<Delete Files="@(TrimmedAssemblies->Metadata('TrimmedAssemblyFileName'))" />
61+
</Target>
3862
</Project>

src/mono/sample/HelloWorld/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ MONO_CONFIG?=Debug
66
MONO_ARCH?=$(shell . $(TOP)eng/native/init-os-and-arch.sh && echo $${arch})
77
TARGET_OS?=$(shell . $(TOP)eng/native/init-os-and-arch.sh && echo $${os})
88
AOT?=false
9+
StripILCode?=false
10+
CompiledMethodsOutputDirectory?= #<path-to-a-writable-directory>
911

1012
#NET_TRACE_PATH=<path-to-trace-of-sample>
1113
#PGO_BINARY_PATH=<path-to-dotnet-pgo-executable>
@@ -18,6 +20,8 @@ publish:
1820
-c $(MONO_CONFIG) \
1921
-r $(TARGET_OS)-$(MONO_ARCH) \
2022
/p:RunAOTCompilation=$(AOT) \
23+
/p:StripILCode=$(StripILCode) \
24+
/p:CompiledMethodsOutputDirectory=$(CompiledMethodsOutputDirectory) \
2125
'/p:NetTracePath="$(NET_TRACE_PATH)"' \
2226
'/p:PgoBinaryPath="$(PGO_BINARY_PATH)"' \
2327
'/p:MibcProfilePath="$(MIBC_PROFILE_PATH)"'

src/tasks/AotCompilerTask/MonoAOTCompiler.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public class MonoAOTCompiler : Microsoft.Build.Utilities.Task
6767
/// - LlvmObjectFile (if using LLVM)
6868
/// - LlvmBitcodeFile (if using LLVM-only)
6969
/// - ExportsFile (used in LibraryMode only)
70+
/// - MethodTokenFile (when using CollectCompiledMethods=true)
7071
/// </summary>
7172
[Output]
7273
public ITaskItem[]? CompiledAssemblies { get; set; }
@@ -152,6 +153,16 @@ public class MonoAOTCompiler : Microsoft.Build.Utilities.Task
152153
/// </summary>
153154
public bool UseDwarfDebug { get; set; }
154155

156+
/// <summary>
157+
/// Instructs the AOT compiler to print the list of aot compiled methods
158+
/// </summary>
159+
public bool CollectCompiledMethods { get; set; }
160+
161+
/// <summary>
162+
/// Directory to store the aot output when using switch compiled-methods-outfile
163+
/// </summary>
164+
public string? CompiledMethodsOutputDirectory { get; set; }
165+
155166
/// <summary>
156167
/// File to use for profile-guided optimization, *only* the methods described in the file will be AOT compiled.
157168
/// </summary>
@@ -437,6 +448,17 @@ private bool ProcessAndValidateArguments()
437448
throw new LogAsErrorException($"Could not find {fullPath} to AOT");
438449
}
439450

451+
if (CollectCompiledMethods)
452+
{
453+
if (string.IsNullOrEmpty(CompiledMethodsOutputDirectory))
454+
throw new LogAsErrorException($"{nameof(CompiledMethodsOutputDirectory)} is empty. When {nameof(CollectCompiledMethods)} is set to true, the user needs to provide a directory for {nameof(CompiledMethodsOutputDirectory)}.");
455+
456+
if (!Directory.Exists(CompiledMethodsOutputDirectory))
457+
{
458+
Directory.CreateDirectory(CompiledMethodsOutputDirectory);
459+
}
460+
}
461+
440462
return !Log.HasLoggedErrors;
441463
}
442464

@@ -712,6 +734,23 @@ private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, st
712734
aotArgs.Add("dedup-skip");
713735
}
714736

737+
if (CollectCompiledMethods)
738+
{
739+
string assemblyName = assemblyFilename.Replace(".", "_");
740+
string outputFileName = assemblyName + "_compiled_methods.txt";
741+
string outputFilePath;
742+
if (string.IsNullOrEmpty(CompiledMethodsOutputDirectory))
743+
{
744+
outputFilePath = outputFileName;
745+
}
746+
else
747+
{
748+
outputFilePath = Path.Combine(CompiledMethodsOutputDirectory, outputFileName);
749+
}
750+
aotArgs.Add($"compiled-methods-outfile={outputFilePath}");
751+
aotAssembly.SetMetadata("MethodTokenFile", outputFilePath);
752+
}
753+
715754
// compute output mode and file names
716755
if (parsedAotMode == MonoAotMode.LLVMOnly || parsedAotMode == MonoAotMode.LLVMOnlyInterp)
717756
{

0 commit comments

Comments
 (0)