Skip to content
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

NativeAOT in .NET 7 #61231

Closed
11 of 29 tasks
agocke opened this issue Nov 4, 2021 · 203 comments
Closed
11 of 29 tasks

NativeAOT in .NET 7 #61231

agocke opened this issue Nov 4, 2021 · 203 comments

Comments

@agocke
Copy link
Member

agocke commented Nov 4, 2021

.NET 6 improvements listed here: dotnet/runtimelab#336

We're now planning the following improvements for NativeAOT in the .NET 7 timeframe:

Goals:

For .NET 7 we want to enable NativeAOT for console apps and native library scenarios. Any libraries which are trim/AOT-warning free should be compatible with these form factors.

Pri 0:

  • Move the NativeAOT project out of dotnet/runtimelab and into dotnet/runtime
    • Building
    • Test integration
    • Packaging
  • Switch to runtime-built NativeAOT packages
  • Onboard first-party dotnet console applications using NativeAOT
  • Perf:
    • At least as fast as on JSON and Plaintext TechEmpower
    • YARP
      • YARP startup time < 50ms
    • Start tracking build time
  • Diagnostics
  • Reproducible and verifiable NativeAOT builds runtimelab#1632
    • CFG
    • CET (Shadow stack)
  • SDK Support
    • MSBuild property for enabling AOT compilation
  • Testing
    • Testing for diagnostic compatibility with the linker
    • Libraries unit testing
  • Docs
    • Building apps
    • Build libraries

Pri 1:

Pri 1 items moved to the future, out of the .NET 7 milestone: #69739

There also are some non-goals for .NET 7, particularly in applications that are not well-suited to trimming:

  • Complex reflection-dependent frameworks, like ASP.NET MVC and WPF
  • Apps with plugin models which dynamically load assemblies, like MSBuild
  • Mobile, WASM (already provided by Mono)
@agocke agocke added this to Needs triage in AppModel .NET 7 via automation Nov 4, 2021
@dotnet-issue-labeler
Copy link

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.

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Nov 4, 2021
@agocke agocke moved this from Needs triage to Team Epics in AppModel .NET 7 Nov 4, 2021
@agocke agocke added area-NativeAOT-coreclr and removed untriaged New issue has not been triaged by the area owner labels Nov 4, 2021
@davidfowl
Copy link
Member

davidfowl commented Nov 5, 2021

I think we can get really far with ASP.NET if user code isn't trimmed but framework code is.

I don't see EF in scope either. How do people do data things? ADO.NET?

@agocke
Copy link
Member Author

agocke commented Nov 5, 2021

At the moment we're sticking with user code not being trimmed by default.

As for EF, I think it strongly depends on what people use. My impression is that grpc is more important for microservice-type apps, but this really isn't my area of expertise. My hope is we can use apps like YARP to drive some of this investigation.

@hez2010
Copy link
Contributor

hez2010 commented Nov 5, 2021

I don't see EF in scope either.

I used to build a demo for using EF with NativeAOT, it requires a bit heavy manual written runtime directives but it works without any problem. However, EF can definitely annotated itself for better trimming support and get rid of the need of runtime directives.

See https://github.com/hez2010/EFCore.NativeAOT

@davidfowl
Copy link
Member

but this really isn't my area of expertise

Luckily, this is my area of expertise 🙃.

I'd like to manifest a document that describes the patterns that are AOT unfriendly. I've spent quite some time with native AOT and ASP.NET Core and it would be nice to have a doc for library authors that want to enable trimming to better understand the rules of the game

@davidfowl
Copy link
Member

@agocke any reason to keep this a package? Why not have it be first class like the other publish experiences?

@snickler
Copy link
Contributor

snickler commented Nov 5, 2021

Awesome! Does this also have a line item for ensuring it works well in regards to modern Desktop application support? This is a huge want for those migrating from UWP and .NET Native.

@agocke
Copy link
Member Author

agocke commented Nov 5, 2021

@davidfowl Thanks for the feedback, much appreciated. So I take it EF is really common? In that case, I think it would be useful to find a representative app to flush out problems. As you know, serializers are probably the most common problem with trimming, so let's see what we can bring into scope.

I'd like to manifest a document that describes the patterns that are AOT unfriendly. I've spent quite some time with native AOT and ASP.NET Core and it would be nice to have a doc for library authors that want to enable trimming to better understand the rules of the game

We've added some documentation for this at https://docs.microsoft.com/en-us/dotnet/core/deploying/trimming/fixing-warnings. Feedback welcome!

Any reason to keep this a package? Why not have it be first class like the other publish experiences?

That's more a technical description in that we need a "package" to ship it in. It seems like we could integrate this with the publish experience, although we might need a workload for additional dependencies. One thing to also keep in mind is that we have a dependency on certain native toolchain pieces as well, like link.exe or an equivalent linker.

@agocke
Copy link
Member Author

agocke commented Nov 5, 2021

@snickler No plans for GUI apps yet. There's been some success experimenting with WinForms -- it's very close to trimmable once ComWrappers is integrated. We'll just need to see how much bandwidth we have for .NET 7 and how difficult it is to make some of these things trimmable/AOT compatible.

@jkotas
Copy link
Member

jkotas commented Nov 5, 2021

migrating from UWP and .NET Native.

This depends on microsoft/CsWinRT#373

@lukemcdo
Copy link

lukemcdo commented Nov 5, 2021

Is there any way a NativeAOT UWP target could be officially supported (or even experimental/beta status) for app services only? This would be a positive tool to help keep modern tools available for UWP while WinUI goes through its teething issues. It would also give a way to build code against .NET 7 and shuffle things out from a UWP code base in-place.

Obviously this wouldn't include official UI support or anything revolutionary.

@davidfowl
Copy link
Member

Will the AOT compiler support the trimming attributes without configuration OOTB, that is, will it only trim assemblies marked as trimmable by default?

@hez2010
Copy link
Contributor

hez2010 commented Nov 5, 2021

will it only trim assemblies marked as trimmable by default?

That's not how NativeAOT work. The NativeAOT compiler generates code at compile-time instead of run-time, and there're no IL code and JIT compiler in compiled artifacts so even if the compiler doesn't trim anything, you still may encounter exception due to missing code at runtime.

For example, for a generic type Foo<T> the compiler need to figure out what Ts are being substituted into before it can generate code for it, so below pattern will results in no code generated for Foo<int>:

private Type innerType;

void Boom(Type t)
{
    typeof(Foo<>).MakeGenericType(new [] { t }); // no generated code for `Foo<int>`
}

void Test()
{
    innerType = typeof(int);
    Test(innerType);
}

Besides, there're lot of even complex patterns that cannot be statically analyzed during compile-time so the compiler can only rely on trimming attributes and runtime directives (rd.xml) and it's hard to be made out-of-the-box.

@MichalStrehovsky
Copy link
Member

Will the AOT compiler support the trimming attributes without configuration OOTB, that is, will it only trim assemblies marked as trimmable by default?

If we ignore nuances related to AOT and generics that @hez2010 mentions above for a moment, the trimming experience should match PublishTrimmed in .NET 6 - by default only assemblies marked IsTrimmable are trimmed (pretty much just the framework at this point) and further configuration is possible through MSBuild properties. That configuration will do the same things wrt trimming irrespective of whether trimming is done by IL Linker or the NativeAOT compiler. It should already be like this in the latest NativeAOT packages from runtimelab. Any behavior difference between a JIT-based world and AOT-based world in trimming would be a bug.

@davidfowl
Copy link
Member

davidfowl commented Nov 5, 2021

@hez2010 thanks for the explain (I know how it works 🙃).

@MichalStrehovsky great!

@filipnavara
Copy link
Member

Are there any plans to port generics sharing from ProjectN?

@MichalStrehovsky
Copy link
Member

Are there any plans to port generics sharing from ProjectN?

If you mean universal shared code, it's not in scope for now. We want to lean into having predictable performance characteristics as opposed to wider compatibility at the cost of unpredictable perf for now.

(Universal shared code turns the generic problem @hez2010 mentioned above into a non-issue because the compiler pregenerates a universal native method body that works for any T. This comes with costs in terms of runtime performance of such method. It works great if such code runs as rarely as possible. But it fills me with dread if such code were to be in a hot path, such as SixLabors/ImageSharp#1703 where the T represents a pixel in a bitmap and the code is going to do hundreds of millions of operations with it.)

@dustinmoris
Copy link

Good to see that .NET is the programming platform for Azure developers only.

I mean the majority of the world runs on AWS but the AWS SDK or GCP SDK is nowhere mentioned here.

This is complete bullshit and I'm sick of being treated like some second class peasant by Microsoft if I'm not using Visual Studio + Azure:

image

@MichalStrehovsky
Copy link
Member

I mean the majority of the world runs on AWS but the AWS SDK or GCP SDK is nowhere mentioned here.

@dustinmoris I understand where you're coming from given the past couple of weeks, but to be 100% clear on what that bullet means - we are not going to special case Azure SDK in .NET or NativeAOT. It came to our attention (or my attention, really because I dealt with the bug) that if someone references a lot of the Azure SDK NuGet packages combined with a bunch of other NuGet packages, the app becomes so big that NativeAOT fails to compile it (Azure/azure-sdk-for-net#24238). Azure libraries really stand out with their size. Trimming needs to be enabled for them using the publicly available mechanism. This just tracks the Azure SDK issue on our side. I've updated the top post to link the issue. I hope that clears it up. The mechanism is public, documented, and anyone can use it.

@dustinmoris
Copy link

@MichalStrehovsky Thanks for the clarification. From the issue it sounded like "let's focus primarily on ASP.NET Core + Azure SDK apps being super efficiently trimmed first".

It came to our attention (or my attention, really because I dealt with the bug) that if someone references a lot of the Azure SDK NuGet packages combined with a bunch of other NuGet packages, the app becomes so big that NativeAOT fails to compile it

Hopefully the team will test this with other SDKs as well so other issues don't go unnoticed for AWS or GCP users.

@En3Tho
Copy link
Contributor

En3Tho commented Nov 5, 2021

Annotating or refactoring all other possible SDKs to be AOT-friendly is not in scope of this issue tbh.

I guess when .Net 7 and native AOT lands MS will have to deal with another wave of "Why Azure works but my beloved XXX SDK not"?

Surely MS have to provide a very careful and thorough guide of how to make libraries AOT friendly. But 1) in a general case this is a library maintainer's duty, not MS. 2) Not all libraries can be refactored to be AOT friendly, especially if they are heavy run-time codegen based.

@hez2010
Copy link
Contributor

hez2010 commented Nov 5, 2021

Hopefully the team will test this with other SDKs as well so other issues don't go unnoticed for AWS or GCP users.

The trimming support is done by annotating the library itself for trimming compatibility. AWS and GCP sdk authors should annotate their own libraries for better trimming support and make sure they're AOT-friendly. That's not something can be done on .NET NativeAOT or ILLinker toolchain side.

@ductai230894
Copy link

ductai230894 commented Aug 24, 2022

I complie c++ lib with TgBot,
But when using with .net 7 using NativeLibrary, my lib build with static library
But when build to native code .net 7 AOT, it show errors:

unresolved external symbol "public: __cdecl TgBot::Bot::Bot(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class TgBot::HttpClient const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??0Bot@TgBot@@QEAA@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBVHttpClient@1@AEBV23@@Z) referenced in function "public: __cdecl MyTelegramClient::MyTelegramClient(void)" (??0MyTelegramClient@@QEAA@XZ)

this is dependency tgbot, have anyway to tell AOT only merge native lib, I only need show some public method to use in .net 7

this is my setting in .csproj

<DirectPInvoke Include="MyTelegramClient" />
<NativeLibrary Include="TelegramBotNative.lib" Condition="$(RuntimeIdentifier.StartsWith('win'))" />

@MichalStrehovsky
Copy link
Member

MichalStrehovsky commented Aug 25, 2022

That looks like MyTelegramClient::MyTelegramClient function in TelegramBotNative.lib references TgBot::Bot::Bot that is not in TelegramBotNative.lib. You need to add the lib that has TgBot::Bot::Bot as another <NativeLibrary> entry.

@rodrigovaras
Copy link

Hi, i recently update my package reference -> Microsoft.DotNet.ILCompiler on my .NET 6 and i noticed that it was broken. I realize now the sample target .NEt7 and use PublishAot property. If we are forced for now to stay on .NET 6 what is the alternative ?

@MichalStrehovsky
Copy link
Member

Hi, i recently update my package reference -> Microsoft.DotNet.ILCompiler on my .NET 6 and i noticed that it was broken

I'm not aware of a conscious break - but it's also not something we test. What's the issue you're running into?

@rodrigovaras
Copy link

rodrigovaras commented Aug 25, 2022

Hi, i recently update my package reference -> Microsoft.DotNet.ILCompiler on my .NET 6 and i noticed that it was broken

I'm not aware of a conscious break - but it's also not something we test. What's the issue you're running into?

We have a simple repro when we move from:
7.0.0-rc.1.22422.23 -> 7.0.0-RC.1.22363.4

On our project we have the snippet:

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Platforms>AnyCPU;x64;x86;arm;ARM64</Platforms>
    <RuntimeIdentifiers>win-x64;win-x86;win-arm64;win-arm</RuntimeIdentifiers>
    <RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
    <IlcOptimizationPreference>Size</IlcOptimizationPreference>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.DotNet.ILCompiler; runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="$(Microsoft_DotNet_ILCompiler)" />
  </ItemGroup>
...
  <Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition=" '$(Platform)' != 'AnyCPU' ">
    <Exec Command="dotnet publish --no-build /p:NativeLib=Shared /p:SelfContained=true /p:RuntimePath=win10-$(Platform.ToLower()) -r win-$(Platform.ToLower()) -c $(Configuration) $(MSBuildThisFile)" />
  </Target>

The publish command basically fails when we move to the new package

@MichalStrehovsky
Copy link
Member

What's the error from the publish command?

@rodrigovaras
Copy link

What's the error from the publish command?

As soon as i stage my other changes i will revert back into the new package and report back. Actually what i remember is not an error but basically the publishing ignoring the AOT generation, so basically ignore the /p:NativeLib=Shared. I tried adding the true..no luck

@rodrigovaras
Copy link

This is the error from the msbuild:
(looks like the tooling is adding the 'win-x64' path to the obj folder which does not exist from the project build
...
PostBuild:
dotnet publish --no-build /p:NativeLib=Shared /p:SelfContained=true -r win-x64 -c Debug Api.
AOT.csproj

C:\Program Files\dotnet\sdk\6.0.303\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Publish.targets(248,5): error MSB3030:
Could not copy the file "D:\mr\mixedreality.eu.proto\client\sdk.net\bin\obj\Api.AOT\x64\Debug\net6.0\win-x64\MixedReal
ity.EU.Api.AOT.pdb" because it was not found. [D:\mr\mixedreality.eu.proto\client\sdk.net\src\Api\Api.AOT\Api.AOT.cspro
j] [D:\mr\mixedreality.eu.proto\client\sdk.net\src\Api\Api.AOT\Api.AOT.csproj]
C:\Program Files\dotnet\sdk\6.0.303\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Publish.targets(248,5): error MSB3030:
Could not copy the file "D:\mr\mixedreality.eu.proto\client\sdk.net\bin\obj\Api.AOT\x64\Debug\net6.0\win-x64\MixedReal
ity.EU.Api.AOT.dll" because it was not found. [D:\mr\mixedreality.eu.proto\client\sdk.net\src\Api\Api.AOT\Api.AOT.cspro
j] [D:\mr\mixedreality.eu.proto\client\sdk.net\src\Api\Api.AOT\Api.AOT.csproj]
D:\mr\mixedreality.eu.proto\client\sdk.net\src\Api\Api.AOT\Api.AOT.csproj(31,5): error MSB3073: The command "dotnet pub
lish --no-build /p:NativeLib=Shared /p:SelfContained=true /p:RuntimePath=win10-x64 -r win-x64 -c Debug Api.AOT.csproj"
exited with code 1.

@rodrigovaras
Copy link

If i remove the 'publish' command from the csproj and just invoke dotnet publish from the CLI with the NativeLib option it succeed but it just publish, NO native lib is being generated. Switch back to the old package and everything works fine. Also i tried a simple project with the new package and it does generate properly the native lib. I guess our additional properties and settings is conflicting with the IL tooling

@rodrigovaras
Copy link

@MichalStrehovsky, i need to get progress to get a latest compiler package but still using .NET 6.
I got a trivial project:

net6 enable true
<ItemGroup>
	<PackageReference Include="Microsoft.DotNet.ILCompiler" Version="7.0.0-rc.1.22422.23" />
</ItemGroup>

run this command but i don't think the IL compiler is being triggered:
dotnet publish /p:NativeLib=Static /p:SelfContained=true -r win-x64
MSBuild version 17.3.0+92e077650 for .NET
Determining projects to restore...
Restored C:\Users\rodrigov\source\repos\ClassLibrary1\ClassLibrary1\ClassLibrary1.csproj (in 278 ms).
ClassLibrary1 -> C:\Users\rodrigov\source\repos\ClassLibrary1\ClassLibrary1\bin\Debug\net6\win-x64\ClassLibrary1.dll
ClassLibrary1 -> C:\Users\rodrigov\source\repos\ClassLibrary1\ClassLibrary1\bin\Debug\net6\win-x64\publish\

If i revert the package the IL runs fine.

@jkotas
Copy link
Member

jkotas commented Aug 31, 2022

We made a change that you always need to set PublishAot property, even if you explicitly reference the package.

@rodrigovaras
Copy link

rodrigovaras commented Sep 1, 2022

net6 enable true
</ItemGroup>
The publish does not seems to trigger the AOT compiler even when adding the property into the project PublishAot=true:

C:\Users\rodrigov\source\repos\ClassLibrary1\ClassLibrary1>dotnet publish /p:NativeLib=Static /p:SelfContained=true /p:PublishAot=true -r win-x64
MSBuild version 17.3.0+92e077650 for .NET
Determining projects to restore...
All projects are up-to-date for restore.
ClassLibrary1 -> C:\Users\rodrigov\source\repos\ClassLibrary1\ClassLibrary1\bin\Debug\net6\win-x64\ClassLibrary1.dll
ClassLibrary1 -> C:\Users\rodrigov\source\repos\ClassLibrary1\ClassLibrary1\bin\Debug\net6\win-x64\publish\

@jkotas
Copy link
Member

jkotas commented Sep 1, 2022

@LakshanF The explicit package reference does not seem to work with .NET 6 SDK anymore. Could you please take a look?

@LakshanF
Copy link
Member

LakshanF commented Sep 1, 2022

The latest ILC package versions expect the SDK to import the needed native AOT targets and the .NET 6 SDK doesn't have this support.

The 7.0 SDK will also warn users when they add explicit package references around versioning concerns since the SDK will use a 'correct' ILC package version that will not have any problems. We still will support explicit package references in 7.0 SDK for some narrow scenarios that we expect users need but that requires the 7.0 SDK.

Having an older version of the ILC package that doesn't have this requirement will make the above scenario work. For example, this version should work,

<PackageReference Include="Microsoft.DotNet.ILCompiler" Version="7.0.0-preview.6.22324.4" />

@mrhelmut
Copy link

mrhelmut commented Sep 2, 2022

So the last version to ever support .NET 6 (and targeting osx until .NET 8?) is 7.0.0-preview.6.22324.4?

That also means that, if there are future ILCompiler 8.0 previews, they will be unusable outside .NET 8 SDK previews by referencing it since the SDK itself overrides the package version?

@filipnavara
Copy link
Member

The new packaging also broke osx-x64 on .NET 7 I think. It's not officially supported by the SDK but the package reference no longer overrides the correct targets and known framework references.

@am11
Copy link
Member

am11 commented Sep 2, 2022

I think we need to wait for #74769 to be part of installers. Right now, SDK is blocked on dotnet/sdk#27406 and installers on dotnet/installer#14340. Last time it took 50+ days for installers to stabilize in v6 to v7 major version switch.

The osx-arm64 port work got affected by this break; we are hitting https://github.com/dotnet/sdk/blob/1e7bcda9c0fea900fcc47661943a280a3f45e320/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs#L367. I will try to patch the sdk. 🤞

@jkotas
Copy link
Member

jkotas commented Sep 2, 2022

The explicit package reference does not seem to work with .NET 6 SDK anymore

@LakshanF fixed this in #75017 / #75030.

targeting osx

dotnet/installer#14443

@dlukitsch
Copy link

Are there any following plans to enable NativeAOT for usage with ARM32 architectures or will it only be available for ARM64 devices?

@MichalStrehovsky
Copy link
Member

Are there any following plans to enable NativeAOT for usage with ARM32 architectures or will it only be available for ARM64 devices?

We would accept community contributions towards enabling it (there were past efforts so it's not far from it), but we don't have current ARM32 plans for NativeAOT. There is a larger discussion on ARM32 in #71042.

@iSazonov
Copy link
Contributor

Currently the ReadOnlySpan<byte> arr = new byte[] {':', ','} is optimized to don't allocate.
My ask is about ReadOnlySpan<char> arr = new char[] {':', ','}. I see a lot of such ones are used in Runtime libraries. If look PowerShell - huge such allocations at startup.

  1. It seems this could be optimized in NativeAOT too.
  2. It seems this could be optimized in R2R too.
  3. It seems this could be optimized in common too since (if I understand right) there are only two cases (LE and BE) and Runtime could select right case at startup without allocation.

Can we have the otimization in .Net 8?

@jkotas
Copy link
Member

jkotas commented Sep 23, 2022

ReadOnlySpan arr = new char[] {':', ','}

This is worked in progress tracked by #60948 and dotnet/roslyn#61414

@UmerEijaz
Copy link

UmerEijaz commented Oct 11, 2022 via email

@dotnet dotnet locked as resolved and limited conversation to collaborators Nov 10, 2022
@stephentoub
Copy link
Member

ReadOnlySpan arr = new char[] {':', ','}

This is worked in progress tracked by #60948 and dotnet/roslyn#61414

dotnet/roslyn's main branch now has this.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Archived in project
Development

No branches or pull requests