dotnet / corert

This repo contains CoreRT, an experimental .NET Core runtime optimized for AOT (ahead of time compilation) scenarios, with the accompanying compiler toolchain.
http://dot.net
MIT License
2.91k stars 510 forks source link

.NET Core 3.1 Web API or Blazor Server app #8078

Open space-alien opened 4 years ago

space-alien commented 4 years ago

I'm trying to get a .NET Core 3.1 web app running with CoreRT.

I'm starting with the Web API project template before attempting to move to the Blazor Server template.

The first thing I had to do was to solve this exception:

System.Reflection.MissingMetadataException: 'System.Text.Json.JsonPropertyInfoNotNullable<WebApplication1.WeatherForecast,System.DateTime,System.DateTime,System.DateTime>' is missing metadata.

Which I did by adding an rd.xml file as follows:

<?xml version="1.0" encoding="utf-8" ?>
<Directives>
  <Application>
    <Assembly Name="System.Text.Json" Dynamic="Required All" />
  </Application>
</Directives>

The web server now gets up and running at least.

However, requests to the Web API project template /weatherforecast endpoint all just fail, with Chrome reporting localhost didn’t send any data. ERR_EMPTY_RESPONSE.

Also, the compiler is still outputting a huge amount of these warnings - all for System.Text.Json:

EXEC : warning : ignoring debug info for [System.Text.Json]System.Text.Json.JsonPropertyInfoCommon`4+<CreateGenericTDeclaredPropertyIEnumerable>d__28<int8,int8,int8,int8>.<>m__Finally1() [C:\Data\Code\repos\Owned\Bakk\WebApplication1\WebApplication1.csproj]
EXEC : warning : ignoring debug info for [System.Text.Json]System.Text.Json.JsonPropertyInfoCommon`4+<CreateGenericTDeclaredPropertyIEnumerable>d__28<int8,int8,int8,int8>.System.Collections.Generic.IEnumerable<TDeclaredProperty>.GetEnumerator() [C:\Data\Code\repos\Owned\Bakk\WebApplication1\WebApplication1.csproj]
EXEC : warning : ignoring debug info for [System.Text.Json]System.Text.Json.JsonPropertyInfoCommon`4+<CreateGenericTDeclaredPropertyIEnumerable>d__28<int8,int8,int8,int8>.System.Collections.IEnumerable.GetEnumerator() [C:\Data\Code\repos\Owned\Bakk\WebApplication1\WebApplication1.csproj]
EXEC : warning : ignoring debug info for [System.Text.Json]System.Text.Json.JsonPropertyInfoCommon`4+<CreateGenericTDeclaredPropertyIEnumerable>d__28<int8,int8,int8,int8>.System.IDisposable.Dispose() [C:\Data\Code\repos\Owned\Bakk\WebApplication1\WebApplication1.csproj]
EXEC : warning : ignoring debug info for [System.Text.Json]System.Text.Json.JsonPropertyInfoCommon`4+<CreateGenericTDeclaredPropertyIEnumerable>d__28<int8,int8,int8,int8>.MoveNext() [C:\Data\Code\repos\Owned\Bakk\WebApplication1\WebApplication1.csproj]
EXEC : warning : ignoring debug info for [System.Text.Json]System.Text.Json.JsonPropertyInfoCommon`4+<CreateGenericTDeclaredPropertyIEnumerable>d__28<int8,int8,int8,int8>.System.Collections.Generic.IEnumerator<TDeclaredProperty>.get_Current() [C:\Data\Code\repos\Owned\Bakk\WebApplication1\WebApplication1.csproj]
EXEC : warning : ignoring debug info for [System.Text.Json]System.Text.Json.JsonPropertyInfoCommon`4+<CreateGenericTDeclaredPropertyIEnumerable>d__28<int8,int8,int8,int8>.System.Collections.IEnumerator.get_Current() [C:\Data\Code\repos\Owned\Bakk\WebApplication1\WebApplication1.csproj]
...

Any thoughts on moving forward with this?

Is it likely to be feasible to get a fairly complex .NET Core 3.1 Blazor web application running with CoreRT at this time? The current 2.1 Web API sample mentions the risk of adding unsupported features and that some functionality might not yet be supported in CoreRT, but I couldn't find any specifics about unsupported features/scenarios elsewhere in the documentation - other than the problem of reflection causing unlinked dependencies.

jkotas commented 4 years ago

The current implementation of System.Text.Json serializer is very unfriendly to full AOT compilation due to heavy reflection use. You can always make it work by adding more hints to the linker, but I do not think it is worth the pain. The System.Text.Json team is not planning to fix this anytime soon (tracked by https://github.com/dotnet/runtime/issues/1568).

If you would like to use full AOT to compile your app, I would recommend switching to Json serializer that has AOT friendly option, e.g. Utf8Json with pre-code generation.

Or not use json serializer at all and directly read/write your json payloads using json reader/writer.

davidfowl commented 4 years ago

@space-alien what are you looking to gain from AOT compilation with CoreRT for your server side blazor application?

space-alien commented 4 years ago

@davidfowl It's for a cross-platform desktop app that would run as a service, with a Blazor UI.

davidfowl commented 4 years ago

And CoreRT is to get you a small binary output or is there more? How small is acceptable?

space-alien commented 4 years ago

I'm turning to AOT for:

  1. Smallest possible binaries. This is important for distribution and for delivering automatic updates. I also expect binary size to have some psychological bearing on the perceived efficiency of the software, although this is not something I can afford to fixate on.
  2. Fast startup time, minimising resource usage. This becomes even more important if users run the app on sign in, rather than as a service.
  3. Perhaps, some additional resistance to decompilation.

In terms of what binary size would be acceptable, I don't have numbers at this stage, but I can say that the preview trimming feature in .NET Core 3 is not yet delivering a viable size reduction for my project.

To illustrate, a Console App template is trimmed to 26,077KB (single file, ReadyToRun) - with a stream of RUNREADYTORUNCOMPILER warnings being emitted. CoreRT, with the most aggressive optimisations, reduces that by 96% to 1,062KB.

And even on a fast system, there is a noticeable lag running the larger trimmed binary (~0.8s before seeing "Hello World" on the first run, with a subtle smaller lag on all subsequent runs), compared to the CoreRT output, which runs instantly every time.

I'm really quite struck by the evident potential of efficient AOT compilation.

davidfowl commented 4 years ago

Thanks for that response @space-alien!

@davidfowl It's for a cross-platform desktop app that would run as a service, with a Blazor UI.

You mentioned that it would run as a service but then you also mention this:

Fast startup time, minimising resource usage. This becomes even more important if users run the app on sign in, rather than as a service.

How much does startup time matter in this case? Isn't the app going to boot up once and then be running for a long time?

Smallest possible binaries. This is important for distribution and for delivering automatic updates. I also expect binary size to have some psychological bearing on the perceived efficiency of the software, although this is not something I can afford to fixate on.

In terms of what binary size would be acceptable, I don't have numbers at this stage, but I can say that the preview trimming feature in .NET Core 3 is not yet delivering a viable size reduction for my project.

Do you have a feel good number where size no longer matters?

To illustrate, a Console App template is trimmed to 26,077KB (single file, ReadyToRun) - with a stream of RUNREADYTORUNCOMPILER warnings being emitted. CoreRT, with the most aggressive optimisations, reduces that by 96% to 1,062KB.

Have you tried running the IL Linker? It can be much smaller than 26MB.

And even on a fast system, there is a noticeable lag running the larger trimmed binary (~0.8s before seeing "Hello World" on the first run, with a subtle smaller lag on all subsequent runs), compared to the CoreRT output, which runs instantly every time.

The current single file implementation on CoreCLR self extracts on first run which causes that horrible lag. I'm not sure it matters for your scenario but that's something that's going to get fixed with .NET 5.

I'm really quite struck by the evident potential of efficient AOT compilation.

This is great! I'd love to see if you get things working with AOT (Just FYI there are lots of warts in higher level frameworks because they weren't designed to be AOT friendly). If you get this app working, please share what the rd.xml looks like and the workarounds you had to put in place.