-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Native AOT Trimming & Perf Improvements in .NET 8 #79003
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas Issue DetailsFor .NET 8 we want to continue improving Native AOT performance, particularly in the areas that Native AOT excels at, namely fast startup, small binaries, and smaller working set. Native AOT shares the JIT and GC with CoreCLR so there's a lot of overlap with CoreCLR in these areas. For .NET 8 we'll target basic APIs that are commonly used by customers and touch multiple areas of the stack (web/http stack and base framework libraries). There are two toy apps that we can use as benchmarks.
|
Native AOT performance is already excellent today. I have been testing it for over a year and it has been fast and stable in this timeframe. To track the performance, I made an early NativeAOT implementation at TechEmpower Benchmarks (named appmpower). One thing I noticed while upgrading last week to .NET 7 at the same time as the asp.net core middleware implementation in the TechEmpower Benchmarks is that the non AOT implementation of the standard middleware plaintext test has improved from 5,703,769 responses per second in .NET 6 to 5,954,942 in .NET 7. My AOT middleware implementation has remained identical (5,024,661 vs 5,026,387 responses per second). I did some testing locally and the whole difference seems due to the |
The AOT code generation can benefit from profile data in similar way as TieredPGO. It requires the profile data to be collected ahead of time and passed to the AOT toolchain. The support is partially implemented - for example, see runtime/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs Lines 29 to 30 in 1412ee7
|
Tagging subscribers to 'linkable-framework': @eerhardt, @vitek-karas, @LakshanF, @sbomer, @joperezr Issue DetailsFor .NET 8 we want to continue improving Native AOT performance, particularly in the areas that Native AOT excels at, namely fast startup, small binaries, and smaller working set. Native AOT shares the JIT and GC with CoreCLR so there's a lot of overlap with CoreCLR in these areas. For .NET 8 we'll target basic APIs that are commonly used by customers and touch multiple areas of the stack (web/http stack and base framework libraries). There are two toy apps that we can use as benchmarks.
Planned perf work in Native AOT includes Size:
Startup perf:
Build time:
|
Is there any doc or guide in the runtime repo, where people can learn how to test NativeAOT with try different csproj switches, see what is there in the native file, usages of RD.XML file, and suggest what can we trim something like that!? So that people can file the issues that they face using NativeAOT which will help the team! |
The trimming options are the same for any trimming (AOT or not). Good starting point is here: https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options?pivots=dotnet-7-0. For AOT specifically - https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ (not trimming related, but stripping symbols for example does have a large size impact). We strongly suggest to not use The tools to inspect size and roots are still mostly missing or are not very user friendly - we have a tracking issue here: #78671 With trimming based on illink (so The AOT compiler can also generate a map file, but I'm not familiar with the details - @MichalStrehovsky should be able to help. |
Hey @vitek-karas, Thanks for the link and write-up that really helped to get started. I was already aware of the first 2 links which are part of public documentation. I had played with those options earlier before .NET 7 release. It was working fine. What I am looking for today is let's say If I created a native executable with NativeAOT today, I want to inspect the executable and see what types have been kept and what has been removed. So that while testing NativeAOT things in the sample project, if I found something which could be removed, but did not get removed, then I can report that thing in GH and can have attention to that issue, which will eventually help team to see why it not removed and see the possibilities. Or not even inspecting the executable, maybe some tool to which I can pass my project or solution path which will publish that and will create a report of types that were removed and which weren't removed because of some reason or annotations. Looking at your description, I guess Linker Analyzer is doing that stuff, but I see examples of Android projects, and also there are some intermediate steps to generate the report. I hope that works with the normal console applications as well. Not sure do the team have any plans to have these tools as dotnet CLI commands so that individual people can inspect their projects and analyze them. I will have a look at DependencyGraphViewer as well. Why these tools are soo under in the repositories, it's very hard to find those! |
Currently the tools are somewhat simple - partly because we didn't need anything more complicated and partly because it turns out to be really difficult do create something more easy to use (@sbomer was looking into something recently in this area).
Mainly because we didn't spend any real effort on these tools. They grew organically as one-off utils somebody wrote to help with certain task and we improved on them over time, but so far we didn't really try to make them useful outside of the small group of people working on the product. That's basically what #78671 is about. |
Ohh understood. Thanks for the info @vitek-karas, it really helps! I will give it a try to DependencyGraphViewer to see what it shows! Hopefully going forward these utils tools will be shipped as CLI tools to help the border audience! :) 🙌 |
If you have a specific scenario in mind, could you please describe it in #78671? Or if you run into something later on, please let us know there. As mentioned above, so far this has been almost exclusively based on internal needs, so having others described what they need would be very helpful. |
Not any scenario as of now, but for sure I will log them inside that thread! I am gonna play with NativeAOT console apps and will see how far we can go. |
BTW a quick question when using |
When I try hello world (for win-x64) with NativeAOT it produces an executable which is 4.8 MB in size (.NET 7). I don't know where you got a working 3kb executable from (honestly if we could do 3kb for hello world by default, we would probably be magicians). Almost all publicly documented trimming options should work with |
DGML files are generated under obj directory. Run |
Ohh thanks @jkotas, do you think it will be helpful to mention that in that README? I can create PR for that! |
@ShreyasJejurkar sure - looking forward to the PR 😉 |
Please have a look #80115 @vitek-karas @jkotas Thank you! |
@ShreyasJejurkar - I've written up what I have been doing to analyze size in AOT apps here: #78671 (comment). |
That is awesome @eerhardt, exactly on point! I will give it a try now. btw @eerhardt right now you have posted those steps in that thread, what do you think would be a good place to have that writeup as part of the repo documentation? So that in case future if someone asks, we can point that user to that single place! Having that in that thread is ok as well! :) |
It wouldn't hurt putting it somewhere in a markdown file in the repo. My hope is that official support will come for tooling in this area, and we can point users to that. |
@eerhardt Yeah. I will see where we can put that. Or if I get the direction on where to put that, I will raise PR for that. Moreover, till the time and tools don't get official, I am planning to create a WebUI where the user can select Following are some features, I am thinking about.
|
Absolutely, this sounds great! The thing I found about size investigations is that one often wants to be able to look at the information from multiple angles to get something actionable. The more tools in the arsenal, the better. One thing I would point out about mstat is that it's versioned - the version of the format is stored as the assembly version. The version in .NET 7 is 1.1 (version 1.0 was short-lived and no need to worry about it). Have the tool check that the major version is 1 to future proof it. If major version changes, it means there were fundamental changes made to the format that are not backwards compatible (and the tool would likely crash trying to parse it). If minor version changes, it just means there could be more info that the tool cannot interpret. That's fine. |
Thanks, @MichalStrehovsky for the reply.
Sure. I got some time to work on the tool, here is the repo link https://github.com/ShreyasJejurkar/MstatReader (Once I get some basic func working, I will deploy this to github pages and will share URL). In README, I posted the screenshot that the tool has. I know the design is not good. I will work on that as well, I will have look for a minimal table feature-rich design because the main goal of mine here is to extract value out of
I understand this, but not sure if will this be problematic for me as of now. If you look in my repo, the |
We're now done with fundamental improvements and we're meeting all our stage1 goals, so I'm going to close this as completed. We can continue to address specific problems as we find them. |
For .NET 8 we want to continue improving Native AOT performance, particularly in the areas that Native AOT excels at, namely fast startup, small binaries, and smaller working set. Native AOT shares the JIT and GC with CoreCLR so there's a lot of overlap with CoreCLR in these areas.
For .NET 8 we'll target basic APIs that are commonly used by customers and touch multiple areas of the stack (web/http stack and base framework libraries). There are two toy apps that we can use as benchmarks.
Albums app
This is an ASP.NET Core Minimal APIs app that simply returns lists of in-memory objects, JSON serialized.):
i. Disk size: 10 MB
ii. Startup time: <50 ms
iii. Working set (before load): <50 MB
iv. Working set (at load): <50 MB
v. Throughput: Within 5% of default CoreCLR RPS on Citrine perf environment ("default" here means compared to the default configuration of a CoreCLR-based deployment of the app, e.g. including tiered JIT)
Todo API app
This app is more representative of something “real” and thus uses much more of the framework surface area:
i. Disk size: 20 MB
ii. Startup time: <150 ms
iii. Working set (before load): <60MB
iv. Working set (at load): <60MB
v. Throughput: Within 5% of default CoreCLR RPS on Citrine perf environment
vi. Container smallest possible constraint: <100MB
The ASP.NET work here is at dotnet/aspnetcore#45910
Planned perf work in Native AOT includes
Size:
.rela.dyn
section on Linux #76657Add benchmarking:
These items don't have improvements planned, but need to be tracked for regressions:
The text was updated successfully, but these errors were encountered: