runtime icon indicating copy to clipboard operation
runtime copied to clipboard

Native AOT is too resource hungry

Open pjmlp opened this issue 1 year ago • 7 comments

When trying to make use of AOT compilation on basic samples with .NET 7 preview 6, it takes a huge amount of time until finally an executable is produced on Linux.

This is on an old Asus 1215B, dual core, with 8 GB and an SSD, from 2009.

Granted this laptop is no speed daemon, however when rewriting the same sample application with managed languages that have been designed with AOT since the beginning like Go, D, Haskell, OCaml, Common Lisp, the whole process is measured in seconds, not minutes, even on such old hardware configuration.

For testing purposes, this is the original C# version, https://github.com/pjmlp/ppm2png/tree/main/csharp

Even when compared with previous experiences in .NET Native, it seems something is wrong in regards to compilation times.

pjmlp avatar Aug 06 '22 16:08 pjmlp

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.

When I tried to compile your project with the latest preview version of ImageSharp, compilation became significantly faster and the resulting executable shrank from 63MB to 6.5MB. Looks like ImageSharp has become more friendly to trimming.

If you want to upgrade your version of ImageSharp, keep in mind that it comes under a different license.

teo-tsirpanis avatar Aug 06 '22 17:08 teo-tsirpanis

Preview 6 still uses the trimming defaults that .NET 6 originally shipped with. With those defaults, we're compiling all of ImageSharp, even if the app only needs PNG support. It takes a long time and produces massive executables. I tried building your app with Preview 6 and again with of the RC1 builds - preview 6 finished in 1:20 on my 2015 i7. RC1 made it in 15 seconds.

It's still not as good as Go or D, but more sane. We don't currently have a way to do incremental compilation (like the others do), so this is compiling everything from Object.ToString to your Main in those 15 seconds. Incremental compilation would be nice to have (because one never has to rebuild the standard libraries that come with the language) but I wouldn't consider it critical since for inner dev loop one is expected to rely on JIT.

For languages that don't have a JIT option, fast AOT compile time is absolutely critical for their success. For .NET, it's a nice to have.

MichalStrehovsky avatar Aug 07 '22 06:08 MichalStrehovsky

To put things in perspective, on the aging laptop mentioned above, the respective build times are:

Go 1.19 D (dmd) (1) D (dmd) (2) D (gdc 10) (1) D (gdc 10) (2) Java (GraalVM 22.2) .NET 7 Preview 6
real 0m0,480s real 0m11,311s real 0m7,398s real 0m19,399s real 0m9,215s real 9m29,085s real 35m2,241s
user 0m0,320s user 0m8,701s user 0m6,108s user 0m16,470s user 0m8,132s user 17m43,751s user 34m3,327s
sys 0m0,178s sys 0m1,695s sys 0m1,125s sys 0m1,814s sys 0m0,870s sys 0m14,373s sys 0m49,241s
  1. With downloading and building imageformats 3rd party dependency.
  2. imageformats 3rd party dependency is already in local build cache

I could also add a Rust version, port the C++20 example to Linux, however I imagine those numbers already describe quite well why I raised the ticket.

I would at least expect similar performace to GraalVM, if you take the point of view of languages where AOT comes in 2nd place.

Maybe when one is lucky to work on latest state of the art developer workstations, it isn't a big deal and thus we get 15s, although it would be nice that the experience "personas" are imagined as developers with average hardware (2009 in 2022 is too much to ask for, I was just curious about the support state).

Anyway here is the feedback, I also added the ports to the same repo, so feel free to make use of it as you wish.

pjmlp avatar Aug 07 '22 12:08 pjmlp

@pjmlp the extremely long times you are observing will be fixed by a newer version of ImageSharp or NativeAOT.

teo-tsirpanis avatar Aug 07 '22 12:08 teo-tsirpanis

@pjmlp Try this instead: https://github.com/hez2010/ppm2png

You need to install a nightly (main) version of .NET 7 from https://github.com/dotnet/installer#installers-and-binaries. On my computer, the compilation process finished within 15 secs.

You can expect the same performance with .NET 7 preview 7 (which will be released next week).

hez2010 avatar Aug 07 '22 13:08 hez2010

To put things in perspective, on the aging laptop mentioned above, the respective build times are:

@pjmlp could you try again with the change that @hez2010 did? It switches to the latest build of NativeAOT. Based on my measurement above, I expect the compile time to go down 5x. This should put .NET before Graal. It will also go down a bit more once we do #67742 that is planned for .NET 7 (based on the experience with crossgen2).

Compilation times similar to Go are only achievable with incremental compilation. Incremental compilation (while still doing the kinds of whole program optimizations we do) is doable, but somewhat lower priority due to having a JIT. Compile times are important and we do look at them, but we have to rank the complexity of various features that impact compile time with other features that we work on.

MichalStrehovsky avatar Aug 08 '22 01:08 MichalStrehovsky

Hi, so tried it out with 7.0.100-rc.1.22407.1 and went nowhere, not only I got lots of errors regarding network connections to the https://pkgs.dev.azure.com/dnceng.... location, now whatever I try ends up with MSBuild not doing anything, as it cached something somewhere.

The .NET 7 Preview 6 works as usual.

I will wait for the next preview release, as I don't feel like messing around my .NET environment to get the nightly bits to actually run.

In any case, I guess this issue is of minor consideration for anyone with good computers for container workloads.

Thanks for taking the time to discuss the issue with me.

pjmlp avatar Aug 08 '22 11:08 pjmlp

@pjmlp can you try adding these lines to your project file?

<ItemGroup>
    <TrimmableAssembly Include="SixLabors.ImageSharp" />
</ItemGroup>

teo-tsirpanis avatar Aug 08 '22 11:08 teo-tsirpanis

@teo-tsirpanis So, changing the ImageSharp version to the latest preview, and trimmable assembly configuration, still with .NET 7 preview 6 has produced this result, building from scratch,

real 1m58,295s user 2m6,454s sys 0m7,256s

This looks magical, compared with the values I previously mentioned.

Thanks once again for the discussions, this all started when I thought about how AOT would work out on middle range hardware, and after the initial disappointment, it appears I was wrong all along and values are more than acceptable.

Although from what I learned, some community education about trimmable Assemblies might also play a role in how the feature will evolve.

Anyway, thanks and I guess we can close this.

pjmlp avatar Aug 08 '22 17:08 pjmlp