Today, we are glad to release .NET 7 Preview 3. The third preview of .NET 7 includes enhancements to observability, startup times, codegen, GC regions, native AOT compilation, and more. The bits are available for you to grab right now and start experimenting with new features like:
- Native AOT
- Default GC regions
- ASP.NET Core startup time improvements
You can download .NET 7 Preview 3, for Windows, macOS, and Linux.
- Installers and binaries
- Container images
- Linux packages
- Release notes
- Known issues
- GitHub issue tracker
.NET 7 Preview 3 has been tested with Visual Studio 17.2 Preview 3. We recommend you use the preview channel builds if you want to try .NET 7 with Visual Studio family products. Visual Studio for Mac support for .NET 7 previews isn’t available yet but is coming soon. Now, let’s get into some of the latest updates in this release.
Faster, Lighter Apps with Native AOT
In the .NET 7 Preview 2 blog post, we announced that the Native AOT project has been moved out of experimental status and into mainline development in .NET 7 in the dotnet/runtime repo. We know that many of you have been eagerly awaiting updates from the team on what’s coming for Native AOT, and we have a couple of new updates for you for Preview 3.
If you want details about Native AOT, or to jump in and get started with it, the repo docs are the best place for that.
We also recognize that some of you might not be familiar with what Native AOT is, so we wanted to share a quick overview of it with you.
What is Native AOT?
Ahead-of-time (AOT) compilation refers to an umbrella of technologies which generate code at application build time, instead of run-time. AOT is not new to .NET. Today we ship ReadyToRun for client and server scenarios, and Mono AOT for mobile and WASM. Native AOT brings full native pre-compilation to .NET desktop client and server scenarios. Native AOT is not replacing these existing technologies, rather it’s offering a new set of capabilities that unlocks new form factors.
Existing AOT-compiled .NET assemblies contain platform-specific data structures and native code to frontload work typically done at runtime. Precompiling these artifacts saves time at startup (e.g. ReadyToRun), and enables access to no-JIT platforms (e.g. iOS). If precompiled artifacts are not present, .NET either falls back to JIT or interpretation (depending on the platform).
Native AOT is similar to .NET’s existing AOT technologies, but it produces only native artifacts. In fact, the Native AOT runtime does not know how to read the .NET assembly file formats – everything is platform-native. The executable file format parsing is fully handled by the underlying operating system.
The main advantage of Native AOT is in startup time, memory usage, accessing to restricted platforms (no JIT allowed), and smaller size on disk. Applications start running the moment the operating system pages in them into memory. The data structures are optimized for running AOT generated code, not for compiling new code at runtime. This is similar to how languages like Go, Swift, and Rust compile. Native AOT is best suited for environments where startup time matters the most. Targeting Native AOT has stricter requirements than general .NET Core/5+ applications and libraries. Native AOT forbids emitting new code at runtime (e.g. Reflection.Emit), and loading new .NET assemblies at runtime (eg. plug-in models).
Prepare your apps for Native AOT
For .NET 7 we are targeting console apps and native libraries as the primary scenario for Native AOT. Application developers and library authors can now take advantage of Native AOT by ensuring that their applications are trimmable. Since trimming is a requirement for Native AOT compilation, preparing your applications and libraries now for trimming will help them get ready for Native AOT as well. If you are an author of any .NET libraries, following the “Trimming libraries” instructions specifically will help you prepare your libraries for trimming and Native AOT.
One of the apps that we’re planning to ship in .NET 7 compiled with Native AOT is the crossgen tool. Crossgen is part of the .NET SDK. It’s the CoreCLR AOT compiler that produces ReadyToRun executables. Crossgen is written in C# and we currently ship it compiled with itself as a ReadyToRun app (it’s turtles all the way down!). We’re already seeing some very promising numbers in terms of compilation speed and size. Crossgen benefits heavily from Native AOT because it’s a short-lived process and the startup overhead dominates the overall execution time:
Scenario | ReadyToRun | NativeAOT |
---|---|---|
Compile CoreLib | 4182 ms | 3512 ms |
Compile HelloWorld | 185 ms | 49 ms |
Configuration | Size |
---|---|
ReadyToRun | 34.8 MB |
NativeAOT | 17.6 MB |
Looking ahead, Native AOT compatibility will be improved over the next few versions of .NET, however there will always be reasons to prefer JIT for many scenarios. We will also add first-class support in the dotnet SDK for publishing projects with Native AOT.
Observability
.NET 7 continues to evolve support for the cloud native OpenTelemetry specification. Preview 3 adds support for specification updates #988 and #1708 that make the trace state mutable for samplers.
// ActivityListener Sampling callback
listener.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) =>
{
activityOptions = activityOptions with { TraceState = "rojo=00f067aa0ba902b7" };
return ActivitySamplingResult.AllDataAndRecorded;
};
System.Composition.Hosting
The latest Managed Extensibility Framework gets a slight update to align with the previous version APIs. The new APIs allow adding a single object instance to the System.Composition.Hosting container. Similar to the functionality provided in the legacy interfaces System.ComponentModel.Composition.Hosting with the API ComposeExportedValue(CompositionContainer, T)
Proposal: Inject existing object into MEF2
namespace System.Composition.Hosting
{
public class ContainerConfiguration
{
public ContainerConfiguration WithExport<TExport>(TExport exportedInstance);
public ContainerConfiguration WithExport<TExport>(TExport exportedInstance, string contractName = null, IDictionary<string, object> metadata = null);
public ContainerConfiguration WithExport(Type contractType, object exportedInstance);
public ContainerConfiguration WithExport(Type contractType, object exportedInstance, string contractName = null, IDictionary<string, object> metadata = null);
}
}
Startup time improvements with Write-Xor-Execute enabled
Performance continues to be a major focus for .NET 7. The dotnet/runtime#65738 PR reimplemented the precode and call counting stubs (tiered compilation helper stubs) to significantly reduce number of post-creation modifications of executable code in the runtime. This resulted in 10-15% startup time improvements.
As a bonus, this change also resulted in steady state performance improvements (upto 8%) in some microbenchmarks and some ASPNet Benchmarks even without Write-Xor-Execute enabled.
However, there are few regressions resulting from that change too (without Write-Xor-Execute enabled) that will be addressed in the upcoming preview releases. These were observed in the Orchard and Fortunes benchmarks on Intel processors only.
CodeGen
Thanks in a large part to community contributors, Preview 3 features several optimizations and bug fixes to code generation and just-in time (JIT) compilation. Here’s an overview of the changes that are available today.
Community PRs
These pull requests were all initiated by community contributors.
From @clamp03
From @SkiFoD
From @sandreenko
From @SingleAccretion
- Fix missing zero-offset sequences and add checking
- Handle direct addresses for statics in IsFieldAddr
- Do not number partial definitions and ARGPLACE nodes
- Use SSA def descriptors in copy propagation
- ZeroObj assertions
- Deduplicate some HWI codegen code
- Use push for 8/12 byte struct args on x86
- Do not set GLOB_REF for invariant indirections
- Do not value number locals on the LHS
- Keep the volatility of CLS_VARs in rationalization
- Slightly more aggressive ASG reversal
- Fix copy propagation
- Count OBJ/BLK as memory uses
- Delete compUnsafeCastUsed
- Fix a couple issues with GTF_GLOB_REF setting
- Do not create small constants while morphing cascading addition
- Do not propagate RHS flags in block morphing
- Stop generating CLS_VAR for 64 bit targets
- A better fix for #66242
- Do not assume containment
- Some small copy propagation changes
From @trympet
From @Wraith2
Dynamic PGO
Arm64
- Morph Vector.Create(0) to Vector.Zero
- Allow constant propagation of Vector.Zero.
- Optimize Arm64 comparison instructions: cmle, cmlt, fcmle, fcmlt
- Better addressing mode for floating point on arm64
- Optimize a % b
- JIT: Faster vector == Vector128.Zero on arm64
Loop Optimizations
- Loop Cloning improved the duration of single invocation by 21% for System.Collections.Tests.Perf_BitArray.BitArrayLeftShift(Size: 512):
General Optimizations
- Eliminate extra copy of struct from a callee that was returned in Hidden Buffer
- Unroll String.Equals and str.StartsWith for constant strings
- Extend Equals/StartsWith auto-vectorization for OrdinalIgnoreCase
- movzx optimization after setcc shows 0.03 ~ 0.16 % code size reduction
GC Regions Enabled by default
With Preview 3, regions functionality which should help with memory utilization for high throughput applications has been enabled by default. The functionality is now enabled for all Platforms except MacOS and NativeAOT (which would be enabled in the future). More details are available in this issue: https://github.com/dotnet/runtime/issues/43844
We expect some working set increases for smaller applications due to how regions are initially allocated. If you notice any functional or performance differences please create an issue within the runtime repo.
Cryptography: Generating X.500 names more robustly
This change simplifies working with certificates by introducing a class that provides more clarity for parsing X.500 names.
Make it safer and easier to build an X500DistinguishedName
Classically, anyone wanting to build a X.500 name (such as for creating test certificates with the CertificateRequest
class did so with string manipulation, either via a simple literal or with string formatting, e.g.
request = new CertificateRequest($"CN={subjectName},OU=Test,O=""Fabrikam, Inc.""", ...);
This is generally fine, except for when subjectName
contains a comma, quote, or anything else that has an influence on the parser. To address that, we added the X500DistinguishedNameBuilder
class. Because every method only operates on a single relative distinguished name (RDN), there’s no ambiguity in parsing. As a bonus, since the RDN identifiers are expanded, you no longer have to guess what “CN” stands for (“Common Name”).
X500DistinguishedNameBuilder nameBuilder = new();
nameBuilder.AddCommonName(subjectName);
nameBuilder.AddOrganizationalUnitName("Test");
nameBuilder.AddOrganizationName("Fabrikam, Inc.");
request = new CertificateRequest(nameBuilder.Build(), ...);
Targeting .NET 7
To target .NET 7, you need to use a .NET 7 Target Framework Moniker (TFM) in your project file. For example:
<TargetFramework>net7.0</TargetFramework>
The full set of .NET 7 TFMs, including operating-specific ones follows.
net7.0
net7.0-android
net7.0-ios
net7.0-maccatalyst
net7.0-macos
net7.0-tvos
net7.0-windows
We expect that upgrading from .NET 6 to .NET 7 should be straightforward. Please report any breaking changes that you discover in the process of testing existing apps with .NET 7.
Support
.NET 7 is a Current release, meaning it will receive free support and patches for 18 months from the release date. It’s important to note that the quality of all releases is the same. The only difference is the length of support. For more about .NET support policies, see the .NET and .NET Core official support policy.
Breaking changes
You can find the most recent list of breaking changes in .NET 7 by reading the Breaking changes in .NET 7 document. It lists breaking changes by area and release with links to detailed explanations.
To see what breaking changes are proposed but still under review, follow the Proposed .NET Breaking Changes GitHub issue.
Roadmaps
Releases of .NET include products, libraries, runtime, and tooling, and represent a collaboration across multiple teams inside and outside Microsoft. You can learn more about these areas by reading the product roadmaps:
Closing
We appreciate and thank you for your all your support and contributions to .NET. Please give .NET 7 Preview 3 a try and tell us what you think!
Hi,
What does Native AOT mean for Blazor?
Thanks.
Please add COMPlus_legacyCorruptedStateExceptionsPolicy
Most people pay attention to the startup speed and size of desktop applications. Console programs are generally used by developers themselves, while dotnet is committed to optimizing the console and ignoring desktop applications. What’s the use of faster and smaller console startup
Any desktop application now, no matter WPF, WinForm, winui or Maui, is too bulky
We are having issues getting net7.0-android to be recognized. We are currently migrating from .net6 and are now getting this error with the android version in:
error NU1012: Platform version is not present for one or more target frameworks, even though they have specified a platform: net7.0-android
error NETSDK1139: The target platform identifier android was not recognized.
Is android not supported in this release?
EDIT: we are using TargetFrameworks instead of TargetFramework: net7.0-windows;net7.0-android
We have to...
I don’t believe the workloads have shipped quite yet, but I did ask and you can find information on supporting your scenario here:
https://github.com/dotnet/maui/wiki/.NET-7-and-.NET-MAUI
https://github.com/dotnet/maui/wiki/Roadmap
https://devblogs.microsoft.com/dotnet/dotnet-maui-rc-1/
Hope that helps.
Was this in response to my post? If so we don't use Maui. The only UI we use is for windows and it's WinForms only to present vulkan. We really want .net 7 for AOT, we had AOT running in the early .net 6 releases but at some point a newer .net 6 release broke it. I can run back and get the last version of .net 6 it last worked...
create a class library, then two projects. One for running android version and one for winforms.
Appreciate the reply, but we did that but because of limitations on packaging, two of the libraries had to be merged into one csproj. We have a small library that uses almost no other references and it wont compile either and it doesnt use winforms at all.
That said, We reverted the test machine back to .net6 and it would not compile any longer either. We removed the .net 7 sdk from add/remove programs...
Will using AOT make the code not readily available through reverse engineering?
Unfortunately, the current applications are easy to browse with e.g. dnSpy
Yes, especially in reflection-free mode.
Missed one important target
net7.0-linux
Of course there are lots of distributions, but by
net7.0-linux
could be meantnet7.0-posix
Looks like Microsoft already started working on it https://www.nuget.org/packages/Mono.Posix/7.1.0-final.1.21458.1
Would’ve loved to see native AOT for WPF. And I’m sure many people would love to see Windows 10 and Windows 11 styles for WPF too, which seems to be planned: https://github.com/dotnet/wpf/issues/5793
The problem is that the current WPF team has only taken over WPF and is also responsible for WinUI as far as I know which is their main job. So WPF has extremely low priority. You can easily see this on the issue response time and how long even simple PR's remain unreviewed for months. It is extremely unlikely that WPF gets any new features. Since it was open sourced it hasn't even got an...
You mean they were lying to us when they said they were hiring for WPF? They have the money and they notice. They know the business world is using WPF and they know that literally nobody cares about the whole garbage WinUI/WinRT stack. Do not accept their excuses, rather find out what nefarious project really has their attention like Pluton and TPM.
What I gather is that TPTB don't like that you can create free-spirited Win32...
Looking at WinUI lack of progress, and exponential set of github issues across all repos related to WinRT and WinUI tooling, they aren't also doing an exception job on that side either.
And those .NET developers that have to deal with C++ stuff, and were robbed of C++/CX, also get to enjoy C++/WinRT with a development experience akin to the good old days of ATL development. Catching up with C++/CX tooling seems to be something, that...
I suppose this is not the right place to post this, but I'm not sure where the right place is.
What we really need from .NET right now is a way to deploy our .NET apps to a remote Linux computer (not WSL) and debug all with one click of the "Debug" button in Visual Studio. This works fine for Linux C++ apps in Visual Studio, but for .NET apps, it requires us to manually...
That would be in the Visual Studio feedback site: https://developercommunity.visualstudio.com/home
Thanks. It appears this feature has been requested already at https://developercommunity.visualstudio.com/t/Convenient-way-to-add-a-remote-debug-con/917516
My thoughts about NativeAOT are:
So thanks for that but the way its (not) implemented it's not really useful, for me at least.
We plan to look into expanding the scenarios where NativeAOT is a good fit over time. It's a function of time and resources. It is already possible to use WinForms with NativeAOT, but it requires some polish and won't be advertised as a supported scenario because of that. I suggest following a .NET community member who helped to make a lot of progress on this over the years: Andrey Kurdyumov - https://twitter.com/Kurdiumov. Here's one of...
What about WPF? It is quite known, also because of the several repo polls, that people are unsatisfied with the WPF development / repo owners so far. The recently updated roadmap doesn't show any NativeAOT support and every time we ask for that we get no answers.
About the output size, like I said. There is a difference of 4.9mb between C++ and C# on a console project just printing "Hello World". I don't know exactly...
Hi Max, I hope you're not expecting a response. I have posted MANY times on both here and the VS blog, and i NEVER get a response to WPF questions. We have a huge WPF codebase and the lack of support for the technology from Microsoft is appalling. Just look at the WPF Roadmap on github that this article links to and its clear there's nothing happening.
We are currently evaluating non MS technology for...
Just a mention because I have one sitting in front of me. A small console app I wrote to do some minor sort/consolidation on some config files on our mail server is 16,384 bytes with .NET Framework 4.8. 163,776 in .NET 6.0 and 165,317 in NET 6.0 with ReadyToRun. Sure, it’s quite a bit larger, but it’s 147kb, not 4.9mb.
The state of dotnet AOT platform support on MAUI is yes for iOS, Mac catalyst, android (via monovm aot), and no for Windows (regression from Xamarin since UWP has AOT but WinUI hasn't).
The regression on Windows is more a matter of politics than time and resources. The work is being done by Andrey but the team is stalling (https://github.com/microsoft/CsWinRT/issues/989#issuecomment-921911755, https://github.com/microsoft/CsWinRT/issues/999). They are treating reflection support as a reason to avoid generics (!), putting a tiny...