An itinerary of performance improvements in .NET 6

Performance Improvements in .NET 6

We have seen improvements in the past half a decade in .NET in terms of functionality and performance, along with a few other components. Microsoft has been creating new possibilities repeatedly, which brings us to an almost new face of .NET after seeing performance improvements in .NET 6.

A year before the Dotnet runtime repository forked away from its main branch, 550 pull requests were considered while creating an entirely new system in the form of an important and massive update.

We can say that with the new update to .NET 6, there is nothing a developer cannot do with this platform. To give you an overview, there is JiT, which was an unexpected addition. Just-in-Time compiler provides inlining system forwarding a major benefit to the developer in terms of optimizations.

Just like this, there are several amazing and crucial additions to .NET 6 features that we are going to discuss in the sections below.

Overview of Major Performance Improvements in .NET 6

1. JiT

Continuing from our discussion on using the JiT compiler in .NET above, understand that code compilation is the core of every application or digital solution ever built. So, an improvement in the code generation has a multiplier effect on the entire code structure. This includes the ability to improve performance, speed, testing, security, etc.

With the changes in the core structure with the new update, developers will benefit from inlining and the devirtualization process. With inlining, the caller enables the code to be deployed directly into the caller. This saves the time and effort required to direct the call through an overhead, but this is a minor benefit. More importantly, this system shares the content of the callee to the caller enabling subsequent or technically called “knock-on” optimizations.

The devirtualization works along with inlining providing better optimizations. With devirtualization, the JiT takes a virtual or an interface method call and statistically identifies the end target of the call. Doing so saves the time required to approach the target directly and saves the cost required for virtual dispatch. With the devirtualization complete, the target is considered inlined.

Furthermore, the revamped JiT structure translates the intermediate language directly into the assembly code at run time. Through this, it is also used as an ahead-of-time compilation, which is a part of the CrossGen2 code optimization system and is deployed in the Ready to Run (R2R) format.

2. Changes to the System Types

The system-oriented changes in the .NET system have a wide-reaching impact. In other words, some changes at the foundational aspects of the system can go a long way in improving the overall performance and structure.

One of the prime examples of these changes is Guid. Guid is one of the .NET features used to provide unique identifiers. These can be for any number of things and operations.

Developers need to create these operations quickly and parse, format, and refine them with the same speed.

Another subtle but important update here is that the Guid.NewGuid can be used on macOS. Earlier, this was not an option on macOS systems due to performance issues. Development for macOS-related solutions were implemented using data read from /dev/urandom, which provided the same cryptographic entropy.

Now, the Guid.NewGuid component returns the same cryptographically strong random-bits by using the CCRandomGenerateBytes.

Among other minor improvements, we have a new System.Text JSON source code generator system that secures to boost performance. Also, the FileStream has been rewritten, leading to fixing the previous I/O performance issues.

3. Transport Layer Security

With the new updates to the TLS component, now it can build secure connections even for a Linux-based solution, which was not possible earlier. Furthermore, by giving support to Linux, the TLS can shorten the time required to create secure connections, speeding up the transactions and processes. Lastly, it can enable a more aggressive way of using spans in the implementation cycle of BigInteger.

4. Collections and LINQ

What’s great about this component is that in every release of .NET, there have been some improvements in collection types and LINQ. From time to time, it has become faster and better than before.

These improvements are deployed with changes to the Dictionary<TKey, TValue> as they are used on multiple occasions for performance improvement.

In another case, loading data from a database, file storage, or an API to store, forward, present, and manipulate the end-users has improved. This is because, among changes in .NET features, improvements to these underlying processes can provide great results.

See an example below;

privateIEnumerable<KeyValuePair<string,int>> _dictionary =Enumerable.Range(0,100).ToDictionary(i=>i.ToString(),StringComparer.OrdinalIgnoreCase);
 	[Benchmark]
publicDictionary<string,int>Clone()=>newDictionary<string,int>(_dictionary);
Method Runtime Mean Ratio
Clone .Net Core 3.1 3.224 us 1.00
Clone .Net 5.0 2.880 us 0.89
Clone .Net 6.0 1.685 us 0.52

Additions like these can impressively stimulate changes in performance in some specific situations. So, you can use them, but make sure to understand their applicability and usage.

5. C# 10

C# 10 is deployed as a part of the new performance improvement in the .NET 6 release and the Visual Studio 2022 update. It includes functions to reduce the number of using with a new global using directive and work with implicit usings for the same purpose.

The traditional using directions and the global using directions mellow together in the new .NET 6 update and lead to overall performance improvement.

Where implicit usings allow developers to add .NET namespaces appropriately related to the project, the global using component lets you bring additional namespaces and use them in the entire project.

Besides this, the C# 10 adds more capabilities to .NET by letting developers code faster and more expressively. It brings several benchmarking benefits, including one worth mentioning, HashData().

6. HashData()

This function computes the hash of data using the SHA256 algorithm for security system cryptography. Follow below for an example;

@page"/counter"
@usingSystem.Security.Cryptography
@usingSystem.Diagnostics
@usingSystem.Text
 
<h1>Hashing</h1>
 
<p>Time:@_time</p>
 
<button class="btnbtn-primary"@onclick="Hash">Click me</button>
 
@code	    {
privateconststringSonnet18=
@"Shall I compare thee to a summer’s day?
Thou art more lovely and more temperate:
Rough winds do shake the darling buds of May,
And summer’s lease hath all too short a date;
Sometime too hot the eye of heaven shines,
And often is his gold complexion dimm'd;
And every fair from fair sometime declines,
By chance or nature’s changing course untrimm'd;
But thy eternal summer shall not fade,
Nor lose possession of that fair thou ow’st;
Nor shall death brag thou wander’st in his shade,
When in eternal lines to time thou grow’st:
So long as men can breathe or eyes can see,
So long lives this, and this gives life to thee.";
 
privateTimeSpan _time;
 
privatevoidHash()
{
byte[] bytes =Encoding.UTF8.GetBytes(Sonnet18);
varsw=Stopwatch.StartNew();
for(inti=0;i<2000;i++)
{
        			_ = SHA256.HashData(bytes);
}
    		_time =sw.Elapsed;
}
}
Method Runtime Result Improvement
Hash .Net 5 JIT 0.454 ms  
Hash .NET 6 JIT 0.280 ms 38%
Hash .NET 6 AOT 0.017 ms 38%

As you can see in the results, with this method, there is a 96% improvement in the results generation and performance.

A Glimpse of Major Changes in .NET 6 Features

The revamped .NET 6 has added significant performance improvements coupled with enhanced ARM support on both Windows and Mac. It also includes a profile-guided optimization (PGO) system, new APIs, etc. Here is an overview of the major improvements and changes;

These and many more performance improvements contribute to give .NET a new face providing better opportunities for the developers.

  • At the same time, there are improvements in Visual Basic, where you will observe a better Visual Studio experience for Windows Forms.
  • Hot Reload removes the need to restart or recompile the code after every change. It allows simultaneous updating of the application as you write the code and update it.
  • In terms of mobile and web application development, .NET 6 brings a better cloud diagnostics system with Open Telemetry and dotnet Monitor. These services are also available and supported in the production stage and work with Azure App Service.
  • The JSON APIs in the improved dot NET version has improved capability and show higher performance while working with a source generator for the serializer.
  • To bring about a positive change in HTTP services associated with .NET, the latest version comes with minimal APIs, which is beneficial for simplifying the beginning (getting started) experience.
  • You can render the Blazor components with JavaScript and integrate them with the existing JavaScript applications.
  • For the BlazorWebAssembly (WASM) applications, .NET 6 provides WebAssembly AOT compilation and support for runtime services, including the relining and native dependencies.
  • Any single page application built with ASP.NET 6 version has gotten a more flexible pattern. These applications can now be used with Angular, React, and other popular frontend frameworks built on JavaScript. 
  • To help HTTPClient and gRPC interact with other HTTP/3 Clients and servers, the .NET 6 features HTTP/3.
  • The .NET version has a re-written FileStream, executed from scratch, which adds support for symbolic links in File IO and higher performance.
  • You can also see better security along with performance improvement in .NET 6. These include higher support for OpenSSL 3, ChaCha20Poly1305 encryption scheme. In terms of security, it has increased for runtime defense-in-depth mitigations, especially for W^X and CET.
  • You can publish single file applications (extraction free) for Linux, macOS, and Windows. In the previous versions, this function was only available for Linux.
  • Among the other improved .NET 6 features, IL Trimming has improved and has become more effective. It brings along new warnings and analyzers meant to improve the final results substantially.
  • The new update comes with source generators and analyzers. They have been specially designed and added to produce better, safer, and higher-performance code.
  • Lastly, large-scale organizations like Red Hat can now build a .NET source and use the same builds to their users.

Conclusion

This sums up the shorter version of the improvements, changes, updates, and modifications to the .NET 6. All these additions have proven to be highly efficient and important in making the development process and experience better. Besides offering better performance, these updates ensure an overall efficient development experience in terms of speed, accuracy, and testing. Leverage the new additions made to .NET 6 features and observe a boost in your productivity and development performance.