We are excited to release.NET 6 Preview 4. We are now about halfway through the.NET 6 release. Now is a good time to look at it again. The full range of NET6. Many features are close to their final form, while others will be rolled out soon as the infrastructure building blocks for the release are in place. Preview 4 lays a solid foundation for delivering the final.NET 6 build in November, with full functionality and experience. If you haven’t tried.NET 6 in your environment, you can now use pull.
Speaking of the final version, we now have a date! Expected on November 9, BBB 0, 11. NET the Conf. 2021. We will be releasing.NET 6 on the 9th, with many in-depth talks and demos that will tell you all about.NET 6.
You can download.NET 6 Preview 4 for Linux, MacOS, and Windows.
- Setup programs and binaries
- Container mirror
- Linux software package
- Release notes
- Known problems
- GitHub Issue Tracker
See the ASP.NET Core and EF Core posts for more details about the new features for the Web and data access solutions. There is also a new.NET Maui post describing the new client application experience, and a hot reload post describing new ways to increase developer productivity.
.NET 6 has been tested with Visual Studio 16.11 and Visual Studio for Mac 8.9. If you want to try.NET 6 in Visual Studio, we recommend you use these versions.
Build 2021
The Microsoft Build conference has already taken place. You’ll definitely want to check out these presentations, which will contain a lot of discussion and demos about.NET 6, showing you the new features and what’s possible now.
- The future of modern application development.NET
- An in-depth look at.NET 6: what’s new and coming
- .NET team “consulting experts”
The.net six theme
We started planning.NET 6 on GitHub in late 2020. We identified eight themes across a broad range of topics, including industry scenarios, support, and education. These topics represent between half and three-quarters of our publishing effort. There are a lot of projects that don’t rise to the level of a topic, or are significant but not a topic (such as support for Apple Silicon devices).
The following are.NET 6 topics, each of which is summarized and described in one sentence. They are listed in the same order as they are shown in Themesof.net.
- .NET is attractive to new developers and students – offering a deliberately simplified experience in Visual Studio products, with clear documentation, a simpler code model and fewer files and concepts, and an intuitive path to deploy artifacts into test and production environments.
- .NET has an outstanding client application development experience — providing a cross-platform client application foundation that seamlessly meets the needs of desktop, mobile, and Web developers, building on and extending existing application types such as Blazor and Xamarin.
- .NET is recognized as a compelling framework for building cloud native applications —— provides basic cloud native functionality focused on performance and observability, improved integration with cloud native and container ecosystems, and a Cloud Native Component (YARP) that shows a lot. NET value with key cloud use cases.
- Enterprise and LTS – Simpler, more predictable models for using.NET with mission-critical applications and to better meet the needs of large enterprise and government customers.
- Develop the.NET ecosystem by improving quality, confidence and support —— Build long-term community partnerships that aim to bring community developers to a similar level to Microsoft and (on the other hand) provide new features and experiences that make it easier for enterprise developers to rely on libraries in community open source projects, Community open source projects are not necessarily associated with or supported by large companies.
- Improve inner loop performance for.NET developers —— Improve developer productivity, including improved build performance, hot restart, and hot reload.
- Improve startup and throughput with runtime execution information (PGO) – Provides a new model based on runtime information to improve performance for faster startup, higher throughput, and smaller binaries.
- Meet developer expectations – make improvements across the.NET product based on feedback and enable new solutions with existing functionality.
The following posts discuss some of these topics in more detail:
- .NET 6 Preview 1
- .NET 6 Preview 2
- The conversation about PGO
.NET platform unification
We’ve talked a lot about.NET unification in past posts and conferences, but it’s missing from the theme. Platform unification has been integrated into everything we do and doesn’t need its own theme. One can think of it as a larger topic than the one listed. It runs through multiple themes and is the underlying assumption for the team to move forward.
The inner loop performance project is a good example. It assumes that.NET 6 applications all share the same foundation, such as using the same build system and libraries. If there are technical differences, such as using a different runtime (CoreCLR or Mono) or code generation technology (AOT or JIT), we take these factors into account and provide a pragmatic and appropriate experience, and tend to have no observable difference in experience. The EventPipe project is another similar example.
Product confidence
We will soon begin releasing an “online” version of production support. Our current target is August. Our development model is oriented towards enabling production workloads, even though we are completing work on all the topics just mentioned.
Product confidence starts at dotnet.microsoft.com. Starting with Preview 1, it runs half of the site load on.NET 6. It’s small, but it’s a mission-critical site for our team and we take it very seriously. .NET 6 has been working for us like a champion.
We also worked with the Microsoft team that deployed the production application on the.NET preview. They did this to take advantage of the new.NET features as early as possible. These teams are always looking for opportunities to reduce the cost of cloud hosting, and deploying the new.NET version has proven to be one of the most effective and labor-saving methods. These teams provide us with early feedback to help us ensure that new features are ready for global production. They also significantly influence the final feature shape because they were our first production users.
All of this early field testing with a real application gives us confidence that.NET 6 will be ready to run your application.
The rest of this article is devoted to the new features in Preview 4.
Tools: Hot reload using the Visual Studio debugger and the Dotnet CLI
Hot reloading is a new experience that lets you edit the source code of an application while it is running without having to manually pause the application or click on a breakpoint. Hot overloading improves developer productivity by reducing the number of times a running application needs to be restarted.
In this release, hot overloading is available for many types of applications, such as WPF, Windows Forms, WinUI, ASP.NET, console applications, and other frameworks running on top of the CoreCLR runtime. We are also working on bringing this technology to WebAssembly, iOS and Android applications that run on top of Mono, but it will still be there (in a preview release later).
To start testing this feature, install Visual Studio 2019 version 16.11 Preview 1 and launch your application using the Visual Studio Debugger (F5). With the application running, you can now use the new options to change the code and apply them using the new Apply Code Changes button, as shown in the figure below.
Hot overloading is also available through the dotnet monitoring tool. Preview 4 contains several fixes to improve the experience.
If you want to learn more about hot reloading, read about it. NET introduction to hot overloading.
System.text. Json support for IAsyncenumerable
IAsyncenumerable
is an important feature added with.NET Core 3.0 and C# 8. New enhancements support System.text.json (de) serialization with an IAsyncenumerable
object.
The following example uses a flow as a representation of any asynchronous data source. The source can be a file on the local machine, or it can be the result of a database query or a Web service API call.
Flow serialization
System.text. Json now supports serializing the IAsyncenumerable <T> value into a JSON array, as shown in the following example.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
static async IAsyncEnumerable<int> PrintNumbers(int n)
{
for (int i = 0; i < n; i++) yield return i;
}
using Stream stream = Console.OpenStandardOutput();
var data = new { Data = PrintNumbers(3) };
await JsonSerializer.SerializeAsync(stream, data); // prints {"Data":[0,1,2]}
IAsyncenumerable only supports the use of asynchronous serialization methods. Attempts to serialize using a synchronized method will result in a NotSupportedException being thrown.
Stream deserialization
Streaming deserialization requires a new API that returns IAsyncenumerable <T>. We added the JsonSerializer DeserializeAsyncEnumerable method, as shown in the following example.
using System; using System.IO; using System.Text; using System.Text.Json; Var stream = new MemoryStream(Encoding.utf8.getBytes ("[0,1,2,3,4]")); await foreach (int item in JsonSerializer.DeserializeAsyncEnumerable<int>(stream)) { Console.WriteLine(item); }
This example deserializes elements on demand and is useful when working with particularly large data streams. It only supports reading from a JSON array at the root level, although it can be relaxed based on feedback in the future.
The existing DeserializeAsync method nominally supports IAsyncenumerable <T>, but within the range of its non-streaming method signature. It must return the final result as a single value, as shown in the following example.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.Json;
var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"{""Data"":[0,1,2,3,4]}"));
var result = await JsonSerializer.DeserializeAsync<MyPoco>(stream);
await foreach (int item in result.Data)
{
Console.WriteLine(item);
}
public class MyPoco
{
public IAsyncEnumerable<int> Data { get; set; }
}
In this example, the deserializer buffers all IAsyncenumerable contents in memory before returning the deserialized object. This is because the deserializer needs to consume the entire JSON value before returning the result.
System.text. Json: Writable DOM functionality
The writable JSON DOM functionality adds a new simple and efficient programming model to System.text.json. This new API is attractive because it avoids the complexities and rituals of serialization and the traditional costs of DOM.
This new API has the following benefits:
- A lightweight alternative to serialization in cases where POCO types are not possible or desirable, or when the JSON schema is not fixed and must be checked.
- Allows valid modifications to a subset of the tree. For example, you can efficiently navigate to a subpart of a large JSON tree and read an array or deserialize a POCO from that subpart. LINQ can also be used with it.
- The use of C# dynamic keywords is allowed, which allows for a loosely typed, more script-like model.
We are looking for feedback on supporting dynamics. If dynamic support is important to you, please give us your feedback.
More details are available at dotnet/runtime #6098.
The writable DOM API
The writable DOM exposes the following types.
namespace System.Text.Json.Node { public abstract class JsonNode {... }; public sealed class JsonObject : JsonNode, IDictionary<string, JsonNode? > {... } public sealed class JsonArray : JsonNode, IList<JsonNode? > {... }; public abstract class JsonValue : JsonNode {... }; }
The sample code
The following example demonstrates the new programming model.
// Parse a JSON object JsonNode jNode = JsonNode.Parse("{"MyProperty":42}"); int value = (int)jNode["MyProperty"]; Debug.Assert(value == 42); // or value = jNode["MyProperty"].GetValue<int>(); Debug.Assert(value == 42); Parse("[10,11,12]"); Parse a JSON array jNode = jsonNode.parse ("[10,11,12]"); value = (int)jNode[1]; Debug.Assert(value == 11); // or value = jNode[1].GetValue<int>(); Debug.Assert(value == 11); // Create a new JsonObject using object initializers and array params var jObject = new JsonObject { ["MyChildObject"] = new JsonObject { ["MyProperty"] = "Hello", ["MyArray"] = new JsonArray(10, 11, 12) } }; // Obtain the JSON from the new JsonObject string json = jObject.ToJsonString(); Console.WriteLine(json); // {" myChildObject ":{" myProperty ":"Hello"," myArray ":[10,11,12]}} // Indexers for property names and array elements are supported and can be chained Debug.Assert(jObject["MyChildObject"]["MyArray"][1].GetValue<int>() == 11);
Microsoft. Extensions. Logging source code generator at compile time
.NET 6 introduced the LoggerMessageAttribute type. This property is Microsoft. Extensions. Part of the Logging namespace, use, it will generate performant Logging API. Source code generation logging support is designed to provide a highly available and high-performance logging solution for modern.NET applications. The automatically generated source code relies on the Ilogger interface and the LoggerMessage.define function.
When LoggerMessageAttribute is used for partial logging methods, the source generator is triggered. When triggered, it can either automatically generate an implementation of the part of the method it is decorating, or it can generate compile-time diagnostics with a prompt for proper usage. Compile-time logging solutions are typically much faster at run time than existing logging methods. It achieves this by minimizing boxing, temporary allocation, and copying.
Using the LoggerMessage.define API directly by hand has the following benefits:
- Shorter and simpler syntax: Declarative attributes are used instead of code boilerplate.
- Guide the developer experience: The generator gives warnings to help the developer do the right thing.
- Supports any number of logging parameters. LoggerMessage.Define supports up to six.
- Support for dynamic logging levels. It is not possible to use LoggerMessage.define alone.
- If you want to keep track of improvements and known issues, see dotnet/runtime\#52549.
Basic usage
To use LoggerMessageAttribute, the consumer class and method need to be partial. The code generator is triggered at compile time and generates implementations of partial methods.
public static partial class Log
{
[LoggerMessage(EventId = 0, Level = LogLevel.Critical, Message = "Could not open socket to `{hostName}`")]
public static partial void CouldNotOpenSocket(ILogger logger, string hostName);
}
In the previous example, the logging method was static and the logging level was specified in the property definition. When you use this property in a static context, you need an ILOGGER instance as a parameter. You can also choose to use this attribute in a non-static context. For more examples and usage scenarios, visit the documentation for the compile-time log source generator.
System. LINQ enhancements
Added new System.linq API for community requests and contributions.
Enumerable support for index and range parameters
The Enumerable.ElementAt method now accepts the index at the end of an Enumerable object, as shown in the following example.
Enumerable.Range(1, 10).ElementAt(\^2); // returns 9
Added the Enumerable.Take overload that takes the Range parameter. It simplifies slicing of enumerable sequences:
- source.Take(.. 3) instead of source.take (3)
- source.Take(3..) Rather than the source. The Skip (3)
- source.Take(2.. 7) instead of source.take (7).skip (2)
- source.Take(^3..) Rather than the source. TakeLast (3)
- source.Take(.. ^3) instead of source.skiplast (3)
- source.Take(^7.. ^3) instead of source.takelast (7).skiplast (3).
Thanks to \@dixin for their contribution to the implementation.
TryGetNonEnumeratedCount
The tryGetNonEnumeratedCount method attempts to get a count that the source can enumerate without forcing enumeration. This approach is useful in cases where it is useful to preallocate buffers before enumeration, as shown in the following example.
List<T> buffer = source.TryGetNonEnumeratedCount(out int count) ? new List<T>(capacity: count) : new List<T>();
foreach (T item in source)
{
buffer.Add(item);
}
TryGetNonEnumeratedCount checks the source that implements ICollection/ICollection
or takes advantage of some internal optimizations adopted by LINQ.
DistinctBy/UnionBy/IntersectBy/ExceptBy
A new variant has been added to the set operation to allow the use of key selector functions to specify equality, as shown in the following example.
Enumerable.Range(1, 20).DistinctBy(x => x % 3); // {1, 2, 3}
var first = new (string Name, int Age)[] { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40) };
var second = new (string Name, int Age)[] { ("Claire", 30), ("Pat", 30), ("Drew", 33) };
first.UnionBy(second, person => person.Age); // { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40), ("Drew", 33) }
MaxBy/MinBy
The maxBy and minBy methods allow you to use the key selector to find the largest or smallest element, as shown in the following example.
var people = new (string Name, int Age)[] { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40) };
people.MaxBy(person => person.Age); // ("Ashley", 40)
Chunk
Chunk can be used to divide enumerable sources into fixed-size slices, as shown in the following example.
IEnumerable<int[]> chunks = Enumerable.Range(0, 10).Chunk(size: 3); // {{0,1,2}, {3,4,5}, {6,7,8}, {9}}
Thanks to Robert Andersson for his contribution to implementation.
FirstOrDefault LastOrDefault/SingleOrDefault override the default parameters
If the source enumeration is empty, the existing FirstOrDefault/LastOrDefault SingleOrDefault method returns the default (T). A new overload has been added, accepting the default parameters to return in this case, as shown in the following example.
Enumerable.Empty<int>().SingleOrDefault(-1); // returns -1
Thanks \ @foxtrek64 for contributing to the implementation.
Accept a ZIP overload of three enumerations
The ZIP method now supports the composition of three enumerable entries, as shown in the following example.
var xs = Enumerable.Range(1, 10);
var ys = xs.Select(x => x.ToString());
var zs = xs.Select(x => x % 2 == 0);
foreach ((int x, string y, bool z) in Enumerable.Zip(xs,ys,zs))
{
}
Thanks to Huo Yaoyuan for his contribution to the implementation.
Significantly improved FileStream performance on Windows
FileStream has been rewritten in.NET 6 for higher performance and reliability on Windows.
The rewrite project has gone through five stages of PR:
- The FileStreamStrategy is introduced as the first step in the FileStream rewrite
- FileStream rewrites Part 2
- File stream optimization
- FileStream rewrite: Use IValueTaskSource instead of TaskCompletionSource
- FileStream rewrite: in AsyncWindowsFileStreamStrategy ValueTaskSource cache
The end result is that FileStream will never block when created for asynchronous IO on Windows. This is a significant improvement. You can see this in benchmarks, as we’ll see shortly.
configuration
The first PR enables FileStream to select an implementation at run time. The most obvious benefit of this mode is that you can switch back to the old.NET 5 implementation, which you can do using the following Settings in runtimeConfig.json.
{
"configProperties": {
"System.IO.UseNet5CompatFileStream": true
}
}
We plan next to add an io_uring policy that takes advantage of the Linux feature of the same name in the recent kernel.
Performance benchmark
Let’s use BenchmarkDotNet to measure improvement.
public class FileStreamPerf { private const int FileSize = 1_000_000; // 1 MB private Memory<byte> _buffer = new byte[8_000]; // 8 kB [GlobalSetup(Target = nameof(ReadAsync))] public void SetupRead() => File.WriteAllBytes("file.txt", new byte[FileSize]); [Benchmark] public async ValueTask ReadAsync() { using FileStream fileStream = new FileStream("file.txt", FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 4096, useAsync: true); while (await fileStream.ReadAsync(_buffer) > 0) { } } [Benchmark] public async ValueTask WriteAsync() { using FileStream fileStream = new FileStream("file.txt", FileMode.Create, FileAccess.Write, FileShare.Read, bufferSize: 4096, useAsync: true); for (int i = 0; i < FileSize / _buffer.Length; i++) { await fileStream.WriteAsync(_buffer); } } [GlobalCleanup] public void Cleanup() => File.Delete("file.txt"); }
` ` ini BenchmarkDotNet = v0.13.0, OS = Windows 10.0.18363.1500 (1909 / November2019Update/h2) 19 Intel Xeon E5-1650 v4 CPU 3.60 GHz, 1 CPU, 12 Logical and 6 Physical Cores. Net SDK= 6.0.100-Preview.5.21267.9 [Host] : NET 5.0.6 (5.0.621.22011), X64 Ryujit Job-OIMCTV: NET 5.0.6 (5.0.621.22011), X64 Ryujit Job-Chfnuy: .net 6.0.0 (6.0.21.26311), X64 Ryujit ‘ ‘
Environment: Windows 10 with SSD drives enabled BitLocker
Results:
- Reading 1 MB files is now two times faster and writing four times faster.
- Memory allocation decreased from 39 KB to 1 KB! That’s a 97.5% improvement!
These changes will provide significant improvements for FileStream users on Windows. For more information, visit dotnet/core #6098.
Enhanced date, time, and time zone support
The following improvements have been made to the date – and time-related types.
New DateOnly and TimeOnly structures
Added date – and time-only constructs with the following characteristics:
- Each represents half of a DateTime, either just the date part, or just the time part.
- DateOnly is ideal for birthdays, anniversaries and workdays. It is the same as the date type of SQL Server.
- Timeonly is ideal for regular meetings, alarm clocks and weekly work hours. It is the same as the SQL Server time type.
- Supplement existing date/time types (DateTime, DateTimeOffset, TimeSpan, TimeZoneInfo).
- In the System namespace, provided in the CoreLib, just like the existing related types.
Performance improvements to datetime.utcnow
This improvement has the following benefits:
- Fixed 2.5x performance regression for system acquisition time on Windows.
- Take advantage of the 5-minute sliding cache of Windows leap second data, rather than retrieving it on every call.
Support for Windows and IANA time zones on all platforms
This improvement has the following benefits:
- When using TimeZoneInfo. FindSystemTimeZoneById implicit conversion (https://github.com/dotnet/runtime/pull/49412)
- Explicit conversion via the new API on TimeZoneInfo: TryConvertIanaIdToWindowsId, TryConvertWindowsIdToIanaId and HasIanaId (https://github.com/dotnet/runtime/issues/49407)
- Improved cross-platform support and interoperability between systems that use different time zone types.
- The deletion requires the use of the TimeZoneConverter OSS library. This feature is now built in.
Improved time zone display name
This improvement has the following benefits:
- From TimeZoneInfo. GetSystemTimeZones returned to eliminate ambiguity in the display name of the list.
- Globalize data using ICU/CLDR.
- Unix only. Windows still uses registry data. This may change in the future.
other
- The display and standard names of the UTC time zone are hardcoded into English and now use the same language as the rest of the time zone data (Currentuiculture on UNIX, the operating system default language on Windows).
- Due to size limitations, the time zone display name in WASM was changed to use the non-localized IANA ID.
- TimeZoneInfo. AdjustmentRule nested classes will be its BaseUtcOffsetDelta internal attribute is set to open, and get a new constructor BaseUtcOffsetDelta as parameters. (https://github.com/dotnet/runtime/issues/50256
- TimeZoneInfo. AdjustmentRule also received other repair on Unix loading time zone (https://github.com/dotnet/run)… , (https://github.com/dotnet/run.)
CodeGen
The following improvements have been made to the Ryujit compiler.
Contribution to the community
@singleaccretion has been busy with the following improvements over the past few months. This is an addition to.NET 6 Preview 3. Thank you very much!
- DOTNET/Runtime #50373 — If the tree is a CSE candidate, do not fold the double negation
- DOTNET/Runtime #50450 — Handles conversion and collapse overflows in value numbers done by a helper
- DOTNET/Runtime #50702 — Remove the must-init requirement for GS Cookie
- DOTNET/Runtime #50703 — Do not confuse FGDispBasicBlocks with FGMorphBlocks
Dynamic PGO
The following enhancements have been made to support dynamic PGO.
- DOTNET/Runtime #51664 — Update the JIT to use the new “LikelyClass” record seen from PGO data processed across generations
- DOTNET/Runtime #50213 — Better tolerance for inconsistencies in edge profile
- Dotnet /runtime #50633 — Fixed mixed PGO/nonPGO compilation
- DOTNET/Runtime #50765 — FGExpandRunRunRelyBlocks
- DOTNET/Runtime #51593 — Modified inline sizing calculation
JIT loop optimization
The following improvements have been made to the cycle optimization.
- DOTNET/Runtime #50982 — Summarize loop reversal
- DOTNET/Runtime #51757 — Do not recalculate the preds list during a circular clone
LSRA
The following improvements have been made to linear scan register allocation (LRSA).
- DOTNET/Runtime #51281 — Improved LRSA statistics to include register selection heuristics
To optimize the
- DOTNET/Runtime #49930 — Folds null check for const string at value number level
- DOTNET/Runtime #50000 — Ininitialize static read-only field for null collapse check of type ref
- DOTNET/Runtime #50112 — Do not assign string literal to potential BBJ_THROW candidates
- Dotnet /runtime #50644 — Enable CSE for vectorx.create
- DOTNET/Runtime #50806 — If there is an unexpected block behind, drop the tail call
- Dotnet /runtime #50832 — Update Vector
to support nint and nuint
- DotNet/Runtime #51409 — Summing up the branch around space-flow optimization
.NET diagnostics: EventPipe for Mono and improved EventPipe performance
EventPipe is.NET’s cross-platform mechanism for outputting events, performance data, and counters. Starting with.NET 6, we have moved the implementation from C++ to C. With this change, Mono will also be able to use EventPipe! This means that CoreCLR and Mono will use the same event infrastructure, including the.NET Diagnostic CLI tool! This change was accompanied by a small reduction in the CoreCLR:
We also made some changes to improve EventPipe throughput under load. In the last few previews, we made a number of changes that increased throughput by 2.06 times as much as.NET 5 can achieve:
- Data collected using the EventPipeStress framework in DotNet/Diagnostics. The writer application writes the event as quickly as possible in 60 seconds. Record the number of successful and discarded events.
For more information, see dotnet/runtime #45518.
IL clipping
Warnings enabled by default
A clipping warning tells you where the clipping might remove code used at run time. These warnings were previously disabled by default because the warnings were very noisy, mainly due to. The ASP.NET platform does not participate in tailoring as a first class solution.
We annotated most of the.NET libraries (runtime libraries, not ASP.NET Core or Windows Desktop Framework) so that they generated accurate clipping warnings. Therefore, we decided it was time to enable clipping warnings by default.
You can use the < SuppressTrimAnalysisWarnings > is set to true to disable the warning. For earlier versions, you can set the same property to false to see clipping warnings.
Tailor warnings bring predictability to the tailoring process and empower the developer. We will continue to annotate more.NET libraries, including ASP.NET Core in future versions. We hope the community will also improve the tailoring ecosystem by commenting more code to ensure secure tailoring.
More information:
- Cropping warnings in.NET 6
- Prepare the.NET library for tailoring
Default clipping mode = link
The new default clipping mode in.NET 6 is linking. Linking TrimMode allows you to crop not only unused assemblies, but also unused members, resulting in significant cost savings.
In.NET 5, clipping attempts to find and remove unreferenced assemblies by default. This is safer, but offers limited benefits. Tailor warnings are now enabled by default and developers can be confident of the results of the tailoring.
As an example, let’s look at this tailoring improvement by tailoring one of the.NET SDK tools. I’m going to use CrossGen, which is the compiler ready to run. It can be clipped with just a few clipping warnings, which the CrossGen team was able to fix.
First, let’s publish CrossGen as a standalone application without any tailoring. It is 80
MB (including the.NET runtime and all libraries).
We can then try the (now older version).NET 5 default clipping mode, CopyUsed. The result drops to 55 MB.
The new.NET 6 default clipping mode link further reduces the standalone file size to 36MB.
We hope that the new link-tailoring mode will better meet the tailoring expectations: significant savings and predictable results.
Share the model with Native AOT
We also implemented the same clipping warning for Native AoT experiments, which should improve the Native AoT compilation experience in much the same way.
Single file publication
The following improvements have been made to single-file application publishing.
Static analysis
A parser for single-file publishing was added in.NET 5 to warn Assembly.Location and other APIs that behave differently in single-file packages.
For.NET 6 Preview 4, we improved the analysis to allow custom warnings. If your API doesn’t work in single-file publishing, you can now tag it with the [RequiresAssemblyFiles] attribute, and a warning will appear if profiler is enabled. Adding this property will also mute all warnings related to a single file in the method, so you can use this warning to propagate warnings up to your public API.
The profiler is automatically enabled for EXE projects when PublishSingleFile is set to true, but you can also enable it for any project by setting EnableSingleFileAnalysis to true. This may be helpful if you want to embed libraries in a single file package.
The compression
Single package now support compression. This can be achieved by the attribute EnableCompressionInSingleFile is set to true to enable. At run time, the file is extracted into memory as needed. Compression can provide significant space savings for some scenarios.
Let’s take a look at a single file publication with and without compression for use with NuGet Package Explorer.
No compression: 172 MB
After compression: 71.6 MB
Compression can significantly increase the startup time of an application, especially on UNIX platforms (because they have a copy-free fast startup path that cannot be used with compression). You should test your application after enabling compression to see if the additional startup costs are acceptable.
PublishReadyTorun now uses CrossGen2 by default
CrossGen2 is now enabled by default when publishing ReadyTorun images. It also optionally supports the generation of composite images.
Expose the following Settings to enable you to configure the publication with code ready to run. These Settings are set to their default values.
PublishReadyTorun now uses CrossGen2 by default
CrossGen2 is now enabled by default when publishing ReadyTorun images. It also optionally supports the generation of composite images.
Expose the following Settings to enable you to configure the publication with code ready to run. These Settings are set to their default values.
CLI installation of the.NET 6 SDK optional workload
.NET 6 will introduce the concept of SDK workloads that can be installed on top of the.NET SDK after the fact to support various scenarios. The new workloads available in Preview 4 are the.NET Maui and Blazor WebAssembly AOT workloads.
For.NET Maui workloads, we still recommend using Preview 4’s Maui-Check tool because it contains additional components that are not yet available in Visual Studio or as.NET SDK workloads. To try the.NET SDK experience (for iOS), run dotnet working install Microsoft-ios-SDK-Full. After installation, you can run DotNet New iOS, and then run DotNet Build to create and build your project.
For Blazor WebAssembly AOT, follow the installation instructions provided on the ASP.NET blog.
Preview 4 includes the.NET Maui workload for iOS, Android, tvOS, MacOS, and MacCatalyst.
Note that the dotnet workload installation copies the workload from Nuget.org to your SDK installation, so if the SDK installation location is protected (meaning at the administrator/root location), then you need to run the lift /sudo.
Built-in SDK version checking
To make it easier to keep track of new versions of the SDK and when the runtime is available, we have added a new command to the.NET 6 SDK: dotNet SDK check
This will tell you what is the latest available version of the.NET SDK and.NET runtime within each feature band.
CLI Template (Dotnet New)
Preview 4 introduces a new template search feature. Dotnet New — Search will search for matching templates at Nuget.org. The data used for this search will be updated more frequently during the upcoming preview.
Templates installed in the CLI are available for CLI and Visual Studio. An earlier issue with missing user installed templates when installing a new version of the SDK has been resolved, but you need to reinstall the templates installed before.NET 6 Preview 4.
Other improvements to template installation include support for the –interactive switch to support authorization credentials for private NuGet sources.
After installing the CLI templates, you can check that the update is available through –update-check and –update-apply. This will now reflect template updates more quickly, support the NuGet source you defined, and support — Interactive authorization credentials.
In preview 4 and upcoming preview releases, the output of the dotnet new command will be cleaned up to focus on the information you need most. For example, dotnet new –install <package> lists only the templates you just installed, not all of them.
To support these and the upcoming changes to Dotnet New, we are making major changes to the template engine API that may affect anyone hosting the template engine. These changes will appear in preview 4 and preview 5. If you are hosting a template engine, please contact us via https://github.com/dotnet/templating, so that we can cooperate with you in order to avoid or minimize the interruption.
support
.NET 6 will be released in November 2021 and will be supported for three years as a Long Term Support (LTS) release. The platform matrix has been significantly extended.
The new content is:
- The android
- IOS
- Mac and Mac Catalyst for x64 and Apple Silicon (aka “M1”)
- Windows ARM64 (especially Windows Desktop)
The.NET 6 Debian container image is based on Debian 11 (” Bullseye “) and is currently being tested.
The end of the
At this point we are in.NET 6. While the final November release seems a long way off, we’re close to finishing feature development. Now is a good time to give feedback, because the shape of the new feature is now set and we’re still in an active development phase, so it’s easy to act on feedback.
Speaking of November, book some time to watch.NET Conf 2021 on November 9, BBB 0, 11. It’s sure to be exciting and fun. We will release the final version of.NET 6 on November 9th, as well as a longer blog post than this one.
Looking for more reading? You can check out our new dialogue series. There are many detailed insights into the new features in.NET 6. If you have any technical questions, please ask them on Microsoft Q&A.
We hope you enjoy trying Preview 4.