dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.96k stars 4.65k forks source link

Optimizing generics by using ILCompiler dependency graph and profile guided optimization in Mono AOT #80941

Open kotlarmilos opened 1 year ago

kotlarmilos commented 1 year ago

Description

Use ILCompiler (NativeAOT compiler) to perform the “pre-pass” analysis and instruct Mono AOT compiler about all the referenced generic types in the program which are only statically reachable. The exchanged information could a list of inflated methods of a generic type for which it can be proven that is not accessed dynamically, in MIBC format as an input for Mono AOT compiler.

To determine which specific instances of generic methods are to be used during runtime and provide this information to the Mono AOT compiler, profile guided optimization (PGO) approach could be used.

This would remove the need for generating generic sharing methods and additional specific instantiations for generic methods and reduce application’s footprint. It should be possible to reuse some of the managed code comprising the dotnet-pgo tool. It would be good to pull the shared code out into a separate assembly (or continue with the current approach that ilc/dotnet-pgo use - share source files).

Tasks

We still have open questions related to the integration and what is required to introduce it as an experimental feature in .NET 8, so comments and feedback are welcome.

/cc: @lambdageek @SamMonoRT

ghost commented 1 year ago

Tagging subscribers to 'os-ios': @steveisok, @akoeplinger See info in area-owners.md if you want to be subscribed.

Issue Details
## Description Use ILCompiler (NativeAOT compiler) to perform the “pre-pass” analysis and instruct Mono AOT compiler about all the referenced generic types in the program which are only statically reachable. The exchanged information could a list of inflated methods of a generic type for which it can be proven that is not accessed dynamically, in MIBC format as an input for Mono AOT compiler. To determine which specific instances of generic methods are to be used during runtime and provide this information to the Mono AOT compiler, [profile guided optimization (PGO)](https://github.com/dotnet/runtime/blob/main/src/coreclr/tools/dotnet-pgo/dotnet-pgo-experiment.md#purpose-of-pgo) approach could be used. This would remove the need for generating generic sharing methods and additional specific instantiations for generic methods and reduce application’s footprint. It should be possible to reuse some of the managed code comprising the dotnet-pgo tool. It would be good to pull the shared code out into a separate assembly (or continue with the current approach that ilc/dotnet-pgo use - share source files). ## Tasks - [ ] ILCompiler dumps dependency graph in a .mibc format - [ ] Enable PGO in Mono AOT engine full-LLVM mode - [ ] Integration and testing of the ILCompiler's dependency graph and the PGO - [ ] PGO with ILCompiler in Mono AOT available as an experimental feature We still have open questions related to the integration and what is required to introduce it as an experimental feature in .NET 8, so comments and feedback are welcome. /cc: @lambdageek @SamMonoRT
Author: kotlarmilos
Assignees: kotlarmilos, ivanpovazan, LeVladIonescu
Labels: `area-Codegen-AOT-mono`, `feature-request`, `os-ios`
Milestone: 8.0.0
SamMonoRT commented 1 year ago

/cc: @lateralusX

ivanpovazan commented 1 year ago

[ ] ILCompiler dumps dependency graph in a .mibc format

Here you can find progress regarding the task: https://github.com/dotnet/runtime/compare/main...ivanpovazan:runtime:nativeaot-mono

The https://github.com/ivanpovazan/runtime/blob/06a300336080793370c7075ccf658abb70869126/src/coreclr/tools/aot/ILCompiler/README.md describes how .mibc file can be generated for a HelloiOS application. This is very much a WIP but can be used as an input to continue working on other tasks/requirements.

I will create a PR once I have something more concrete.

PS Thanks @MichalStrehovsky for the initial work.

kotlarmilos commented 1 year ago

Good, it can be used as an input for testing PGO in Mono AOT.

I will create a PR once I have something more concrete.

Can it work with both Mono and Native AOT as a single tool?

ivanpovazan commented 1 year ago

Can it work with both Mono and Native AOT as a single tool?

Not at this point. Since our main objective is improving codegen for iOS, we will have to enable building ILCompiler for this platform or extract the dependency scanning feature into a separate tool which is platform agnostic. This is yet to be defined.

MichalStrehovsky commented 1 year ago

extract the dependency scanning feature into a separate tool which is platform agnostic

I consider this outcome more likely. The general shape of the dependency analysis is similar, but the dependency graph that NativeAOT is building is geared towards generating an object file for the NativeAOT runtime with any/all optimizations applicable to that model and I think there's going to be enough of small differences that we'll not want to use the exact same classes.

The more likely outcome is that we would be sharing some source files and potentially ILCompiler.DependencyAnalysis/ILCompiler.TypeSystem assemblies, but it would be a different tool at this point.

ivanpovazan commented 1 year ago

Status update

This is a status update on the progress regarding optimizing generics by using NativeAOT dependency analysis guide optimization (DAGO) with Mono in full AOT compilation. The following has been done:

Observations

The current setup works for HelloiOS sample and shows the following results:

Mode Size (bytes) Size (MB) Saving
GSHAREDVT 27980822 27,98 N/A
noGSHAREDVT 26412238 26,41 -5,61%
DAGO+noGSHAREDVT 26734318 26,73 -4,45%

However, further inspection of how impactful would it be to apply the same principle on MAUI iOS applications showed some obstacles:

Follow-up work

Final notes