{"id":32581,"date":"2021-04-08T13:32:58","date_gmt":"2021-04-08T20:32:58","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=32581"},"modified":"2021-04-14T18:35:19","modified_gmt":"2021-04-15T01:35:19","slug":"announcing-net-6-preview-3","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-preview-3\/","title":{"rendered":"Announcing .NET 6 Preview 3"},"content":{"rendered":"<p>Today, we are delighted to release .NET 6 Preview 3. This release is dedicated almost entirely to low-level performance features. These are the types of improvements that many folks don&#8217;t necessarily always fully appreciate, but they help a lot for many apps. Most of these improvements apply to the CLR type system directly, either making it function faster or better interplay with modern CPUs (think &#8220;hardware accelerate the type system&#8221;). In the last few years, there have been a few key performance trends with .NET, including: using structs more liberally in libraries, and moving runtime code to C#. Both of trends are visible (directly or indirectly) in these changes. It also demonstrates continued efforts on a focused set of performance strategies.<\/p>\n<p>You will notice that two of these performance changes came from <a href=\"https:\/\/github.com\/benaadams\/\">Ben Adams<\/a>. He&#8217;s well known for word play on his <a href=\"https:\/\/github.com\/benaadams\/System.Ben\">first name<\/a>. In the spirit of April 1st (recently past), perhaps we can virtually rename this release to .NET 6 Preview B3n. Thanks B3n!<\/p>\n<p>You&#8217;ll also see performance contributions from <a href=\"https:\/\/github.com\/nathan-moore\">Nathan Moore<\/a> and <a href=\"https:\/\/github.com\/SingleAccretion\">SingleAccretion<\/a>. Thanks!<\/p>\n<p>You can <a href=\"https:\/\/dotnet.microsoft.com\/download\/dotnet\/6.0\">download .NET 6 Preview 3<\/a>, for Windows, macOS, and Linux.<\/p>\n<ul>\n<li><a href=\"https:\/\/dotnet.microsoft.com\/download\/dotnet\/6.0\">Installers and binaries<\/a><\/li>\n<li><a href=\"https:\/\/hub.docker.com\/_\/microsoft-dotnet\">Container images<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/core\/blob\/main\/release-notes\/6.0\/install-linux.md\">Linux packages<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/core\/tree\/main\/release-notes\/6.0\">Release notes<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/core\/blob\/main\/release-notes\/6.0\/known-issues.md\">Known issues<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/core\/issues\/6141\">GitHub issue tracker<\/a><\/li>\n<\/ul>\n<p>See the <a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/asp-net-core-updates-in-net-6-preview-3\/\">ASP.NET Core post<\/a> for more detail on what\u2019s new for web technology. For EF Core, <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.EntityFrameworkCore\/6.0.0-preview.3.21201.2\">Preview 3<\/a> includes several bug fixes and ongoing improvements to infrastructure to support upcoming features including compiled models and temporal tables<\/p>\n<p>.NET 6 has been tested with Visual Studio 16.10 Preview 1 and Visual Studio for Mac 8.9. We recommend you use those builds if you want to try .NET 6.<\/p>\n<blockquote><p><strong>For Linux users<\/strong>: .NET SDK 6 Preview 3 resolves an issue where <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/net-5-nuget-restore-failures-on-linux-distributions-using-nss-or-ca-certificates\/\">NuGet restore fails on Linux<\/a> due to expired NuGet certificates and unfortunate interactions with changes made to root certificates stores on Linux, carried by ca-certificates and nss packages. Please update your <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/net-april-2021-updates\/\">.NET 5<\/a> and .NET 6 SDK deployments on Linux, ASAP.<\/p><\/blockquote>\n<h2>Support<\/h2>\n<p>.NET 6 will be released in November 2021, and will be supported for three years, as a <a href=\"https:\/\/github.com\/dotnet\/core\/blob\/main\/release-policies.md\">Long Term Support (LTS) release<\/a>. The <a href=\"https:\/\/github.com\/dotnet\/core\/blob\/main\/release-notes\/6.0\/supported-os.md\">platform matrix<\/a> has been significantly expanded.<\/p>\n<p>The additions are:<\/p>\n<ul>\n<li>Android.<\/li>\n<li>iOS.<\/li>\n<li>Mac and Mac Catalyst, for x64 and Apple Silicon (AKA &#8220;M1&#8221;).<\/li>\n<li>Windows Arm64 (specifically Windows Desktop).<\/li>\n<\/ul>\n<p>.NET 6 Debian container images are based on Debian 11 (&#8220;bullseye&#8221;), which is <a href=\"https:\/\/wiki.debian.org\/DebianBullseye\">currently in testing<\/a>.<\/p>\n<h2>Libraries<\/h2>\n<p>The following APIs and improvements have been added to the .NET libraries.<\/p>\n<h2>Faster handling of structs as Dictionary values<\/h2>\n<p>A new <em>unsafe<\/em> api &#8212; <a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/49388\">CollectionsMarshal.GetValueRefOrNullRef<\/a> &#8212; has been added that makes updating struct values in Dictionaries faster. The new API is intended for high performance scenarios, not for general purpose use. It returns a <code>ref<\/code> to the struct value which can then be updated in place with typical techniques.<\/p>\n<p>Prior to this change, updating <code>struct<\/code> dictionary values can be expensive for high-performance scenarios, requiring a dictionary lookup and a copy to stack of the <code>struct<\/code>; then after changing the <code>struct<\/code>, it needs to be assigned to the dictionary key again resulting in another look up and copy operation. This improvement reduces the key hashing to 1 (from 2) and removes all the struct copy operations.<\/p>\n<p>Example:<\/p>\n<pre><code class=\"cs\">ref MyStruct value = ref CollectionsMarshal.GetValueRefOrNullRef(dictionary, key);\r\n\/\/ Returns Unsafe.NullRef&lt;TValue&gt;() if it doesn't exist; check using Unsafe.IsNullRef(ref value)\r\nif (!Unsafe.IsNullRef(ref value))\r\n{\r\n    \/\/ Mutate in-place\r\n    value.MyInt++;\r\n}\r\n<\/code><\/pre>\n<p>Credit to <a href=\"https:\/\/github.com\/benaadams\">Ben Adams<\/a>.<\/p>\n<h2>Faster interface checking and casting<\/h2>\n<p><a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/49257\">Interface casting performance has been boosted<\/a> by 16% &#8211; 38%. This improvement is particularly useful for C#&#8217;s pattern matching to and between interfaces.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/user-images.githubusercontent.com\/1142958\/112411698-3f413600-8d15-11eb-899f-5a0450524b08.png\" alt=\"image\" \/><\/p>\n<table>\n<thead>\n<tr>\n<th>Method<\/th>\n<th>Implementation<\/th>\n<th align=\"right\">Mean<\/th>\n<th>Version<\/th>\n<th align=\"right\">Ratio<\/th>\n<th align=\"right\">Improvement<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>IsInterface1<\/td>\n<td>Interfaces1<\/td>\n<td align=\"right\">2.166 ns<\/td>\n<td>.NET 6 Preview 2<\/td>\n<td align=\"right\">1.000<\/td>\n<td align=\"right\"><\/td>\n<\/tr>\n<tr>\n<td>IsInterface1<\/td>\n<td>Interfaces1<\/td>\n<td align=\"right\">1.629 ns<\/td>\n<td>.NET 6 Preview 3<\/td>\n<td align=\"right\"><strong>0.752<\/strong><\/td>\n<td align=\"right\">x1.3<\/td>\n<\/tr>\n<tr>\n<td>IsNotImplemented<\/td>\n<td>Interfaces1<\/td>\n<td align=\"right\">2.166 ns<\/td>\n<td>.NET 6 Preview 2<\/td>\n<td align=\"right\">1.000<\/td>\n<td align=\"right\"><\/td>\n<\/tr>\n<tr>\n<td>IsNotImplemented<\/td>\n<td>Interfaces1<\/td>\n<td align=\"right\">1.950 ns<\/td>\n<td>.NET 6 Preview 3<\/td>\n<td align=\"right\"><strong>0.900<\/strong><\/td>\n<td align=\"right\">x1.1<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td><\/td>\n<td align=\"right\"><\/td>\n<td><\/td>\n<td align=\"right\"><\/td>\n<td align=\"right\"><\/td>\n<\/tr>\n<tr>\n<td>IsInterface1<\/td>\n<td>Interfaces6<\/td>\n<td align=\"right\">2.155 ns<\/td>\n<td>.NET 6 Preview 2<\/td>\n<td align=\"right\">1.000<\/td>\n<td align=\"right\"><\/td>\n<\/tr>\n<tr>\n<td>IsInterface1<\/td>\n<td>Interfaces6<\/td>\n<td align=\"right\">1.936 ns<\/td>\n<td>.NET 6 Preview 3<\/td>\n<td align=\"right\"><strong>0.898<\/strong><\/td>\n<td align=\"right\">x1.1<\/td>\n<\/tr>\n<tr>\n<td>IsInterface2<\/td>\n<td>Interfaces6<\/td>\n<td align=\"right\">2.161 ns<\/td>\n<td>.NET 6 Preview 2<\/td>\n<td align=\"right\">1.000<\/td>\n<td align=\"right\"><\/td>\n<\/tr>\n<tr>\n<td>IsInterface2<\/td>\n<td>Interfaces6<\/td>\n<td align=\"right\">1.908 ns<\/td>\n<td>.NET 6 Preview 3<\/td>\n<td align=\"right\"><strong>0.883<\/strong><\/td>\n<td align=\"right\">x1.1<\/td>\n<\/tr>\n<tr>\n<td>IsInterface3<\/td>\n<td>Interfaces6<\/td>\n<td align=\"right\">2.188 ns<\/td>\n<td>.NET 6 Preview 2<\/td>\n<td align=\"right\">1.000<\/td>\n<td align=\"right\"><\/td>\n<\/tr>\n<tr>\n<td>IsInterface3<\/td>\n<td>Interfaces6<\/td>\n<td align=\"right\">1.672 ns<\/td>\n<td>.NET 6 Preview 3<\/td>\n<td align=\"right\"><strong>0.764<\/strong><\/td>\n<td align=\"right\">x1.3<\/td>\n<\/tr>\n<tr>\n<td>IsInterface4<\/td>\n<td>Interfaces6<\/td>\n<td align=\"right\">2.346 ns<\/td>\n<td>.NET 6 Preview 2<\/td>\n<td align=\"right\">1.000<\/td>\n<td align=\"right\"><\/td>\n<\/tr>\n<tr>\n<td>IsInterface4<\/td>\n<td>Interfaces6<\/td>\n<td align=\"right\">1.965 ns<\/td>\n<td>.NET 6 Preview 3<\/td>\n<td align=\"right\"><strong>0.838<\/strong><\/td>\n<td align=\"right\">x1.2<\/td>\n<\/tr>\n<tr>\n<td>IsInterface5<\/td>\n<td>Interfaces6<\/td>\n<td align=\"right\">3.122 ns<\/td>\n<td>.NET 6 Preview 2<\/td>\n<td align=\"right\">1.000<\/td>\n<td align=\"right\"><\/td>\n<\/tr>\n<tr>\n<td>IsInterface5<\/td>\n<td>Interfaces6<\/td>\n<td align=\"right\">2.173 ns<\/td>\n<td>.NET 6 Preview 3<\/td>\n<td align=\"right\"><strong>0.696<\/strong><\/td>\n<td align=\"right\">x1.4<\/td>\n<\/tr>\n<tr>\n<td>IsInterface6<\/td>\n<td>Interfaces6<\/td>\n<td align=\"right\">3.472 ns<\/td>\n<td>.NET 6 Preview 2<\/td>\n<td align=\"right\">1.000<\/td>\n<td align=\"right\"><\/td>\n<\/tr>\n<tr>\n<td>IsInterface6<\/td>\n<td>Interfaces6<\/td>\n<td align=\"right\">2.687 ns<\/td>\n<td>.NET 6 Preview 3<\/td>\n<td align=\"right\"><strong>0.774<\/strong><\/td>\n<td align=\"right\">x1.3<\/td>\n<\/tr>\n<tr>\n<td>IsNotImplemented<\/td>\n<td>Interfaces6<\/td>\n<td align=\"right\">3.644 ns<\/td>\n<td>.NET 6 Preview 2<\/td>\n<td align=\"right\">1.000<\/td>\n<td align=\"right\"><\/td>\n<\/tr>\n<tr>\n<td>IsNotImplemented<\/td>\n<td>Interfaces6<\/td>\n<td align=\"right\">3.071 ns<\/td>\n<td>.NET 6 Preview 3<\/td>\n<td align=\"right\"><strong>0.843<\/strong><\/td>\n<td align=\"right\">x1.2<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>One of the biggest advantages of moving parts of the .NET runtime from C++ to managed C# is that it <a href=\"https:\/\/twitter.com\/ben_a_adams\/status\/1368445229003636737\">lowers the barrier to contribution<\/a>. This includes interface casting, which was moved to C# as an early .NET 6 change. Many more people in the .NET ecosystem are literate in C# than C++ (and the runtime isn&#8217;t even regular C++). Just being able to read some of the code that composes the runtime is a major step to developing confidence in contributing, in its various forms.<\/p>\n<p>Credit to <a href=\"https:\/\/github.com\/benaadams\">Ben Adams<\/a>.<\/p>\n<h2>Runtime: Codegen<\/h2>\n<p>The following changes improve code generation in RyuJIT, either making the process more efficient or the resulting code faster to run. A recent post on <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/loop-alignment-in-net-6\/\">Loop Alignment<\/a> does a great job of demonstrating the level of consideration and detail that is required for optimal performance.<\/p>\n<h3>Optimizations:<\/h3>\n<ul>\n<li><a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/40180\">Remove bounds checks with tests against length<\/a> Credit: <a href=\"https:\/\/github.com\/nathan-moore\">Nathan Moore<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/49271\">Span bounds check elision with top-level range check nodes removal<\/a> Credit <a href=\"https:\/\/github.com\/SingleAccretion\">SingleAccretion<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/48894\">Support loop cloning of byte array accesses<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/48589\">JIT: Non-void ThrowHelpers<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/44419\">CSE for floating-point constants<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/44562\">Invariant static readonly fields to enable CSE\/Hoist-from-loops optimizations<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/49930\">Fold more with null checks for const string<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/49879\">Zero init elimination: Don\u2019t init tracked temps without GC fields<\/a><\/li>\n<\/ul>\n<h3>Dynamic PGO<\/h3>\n<ul>\n<li><a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/48773\">JIT: profile updates for return merges and tail calls<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/48707\">Class profile: Use unknown placeholder for collectible class typehandle<\/a><\/li>\n<\/ul>\n<h3>Keep structs in register<\/h3>\n<ul>\n<li><a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/48377\">Completed struct improvement, part1: create more LCL_FLD\u00a0<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/48797\">Improve liveness for &#8216;STORE_BLK(lcl_var)&#8217;<\/a><\/li>\n<\/ul>\n<h3>Completed .NET 6 EH Write Thru<\/h3>\n<ul>\n<li><a href=\"https:\/\/github.com\/dotnet\/runtime\/issues\/35923\">JIT: Enable EH Write Thru by default<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/47307\">Enregister EH var that are single def<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/DrewScoggins\/performance-2\/issues\/4275\">7 ~ 18% perf improvement<\/a><\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/user-images.githubusercontent.com\/63486087\/112660549-d213ca80-8e12-11eb-8f6b-6c692dd1824a.png\" alt=\"performance improvement\" \/><\/p>\n<h2>Tools: Initial .NET Hot Reload support now available for web apps<\/h2>\n<p>Early support for .NET Hot Reload is now available for ASP.NET Core &amp; Blazor projects using <code>dotnet watch<\/code>. .NET Hot Reload applies code changes to your running app without restarting it and without losing any app state. Code changes that cannot be applied to the running app can still be applied by rebuilding and restarting the app.<\/p>\n<p>This is just the first step in our more comprehensive plan to bring this technology to all .NET developers including desktop (WPF, WinUI, WinForms), cross-platform client scenarios in .NET MAUI, and more. .NET Hot Reload will be supported with these additional platforms in future preview releases of .NET 6. In addition, we will also make .NET Hot Reload available as an integrated experience in future Visual Studio releases.<\/p>\n<p>For more details on trying out hot reload with web app projects, see <a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/asp-net-core-updates-in-net-6-preview-3\/.\">ASP.NET Core updates in .NET 6 Preview 3<\/a><\/p>\n<h2>Closing<\/h2>\n<p>We&#8217;re now about halfway through the .NET 6 release, at least in terms of feature development. You can read about other features that have been added, in the <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-preview-2\/\">Preview 2<\/a> and <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-preview-1\/\">Preview 1<\/a> releases. We expect some larger features to land in the next few previews before we start into focusing on quality in the release candidate builds.<\/p>\n<p>I started the post raising visibility on some great community contributions. Some community folks are using the <a href=\"https:\/\/github.com\/sponsors\">GitHub Sponsors<\/a> program to support spending more of their time on contributing to .NET. That&#8217;s great. <a href=\"https:\/\/github.com\/sponsors\/benaadams\">Ben is an example<\/a>. I encourage you to consider supporting community developers improving .NET, perhaps focused on a part of the product you depend on significantly. It&#8217;s a good opportunity to invest in your supply chain.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>.NET 6 Preview 3 is now available.<\/p>\n","protected":false},"author":1312,"featured_media":21638,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,196],"tags":[4],"class_list":["post-32581","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-dotnet-core","tag-net"],"acf":[],"blog_post_summary":"<p>.NET 6 Preview 3 is now available.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/32581","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/1312"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=32581"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/32581\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/21638"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=32581"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=32581"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=32581"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}