DEV Community

Cover image for What 's new in .NET 7?
Unicorn Developer
Unicorn Developer

Posted on • Originally published at pvs-studio.com

What 's new in .NET 7?

.NET 7 is now available, which means that we can enjoy all sorts of new features and enhancements. Let's talk about the most interesting improvements: C# 11, containers, performance, GC, and so on.

C# 11

We have already posted an article and described the novelties in C# 11. In that article, we covered new features: generic math support, raw string literals, the required modifier, the type parameters in attributes, and so on.

By the way, we are already working on .NET 7 and C# 11 support — we plan to add it to PVS-Studio 7.22. The release is scheduled for early December, and here is the link to download the latest version of the analyzer. If you can't wait to try the beta now, feel free to contact us :)

Native AOT

AOT (ahead-of-time) – compilation of the application not into intermediate, but immediately into machine code. Native AOT uses the ahead-of-time compiler to compile IL into machine code while publishing a self-contained application. The dev team of .NET 7 moved native AOT from experimental status to mainstream development. The biggest advantages of native AOT apps are:

  • startup time;
  • memory usage;
  • access to restricted platforms (where JIT is not allowed).

Native AOT applications come with a few limitations:

  • no dynamic loading (for example, Assembly.LoadFile);
  • no runtime code generation (for example, System.Reflection.Emit);
  • no C++/CLI;
  • etc.

On Stack Replacement (OSR)

In .NET, there is such a thing as tiered compilation. In simple terms, tiered compilation improves the startup time of an application. How? Initially, JIT generates poorly optimized machine code (tier-0) for methods because it simply takes less time. If the number of method calls exceeds a certain threshold, JIT generates more optimized code for this method (tier-1). This approach does not work, for example, with loops, because this can degrade the performance. By the way, at the moment there are only two levels.

OSR allows you to replace the machine code that is currently running with a new, more optimized one. Previously, this feature was only available between method calls. This approach allows you to apply tiered compilation to all methods. This results in quicker compilation with stable performance at the same time. According to Microsoft's tests, the technology helped to speed up the startup of high-load applications by 25%. OSR in .NET 7 is enabled by default for x64 and Arm64.

Central package management (CPM)

Dependency management for multi-project solutions can be a challenge. In situations where you manage common dependencies for many different projects, you can use NuGet's central package management. To get started with central package management, create the Directory.Packages.props file at the root of your solution. Because of CPM, the package version is only specified in Directory.Packages.props, and projects only need to reference the package.

GC Regions

GC Regions is a feature that has been under development for several years. If earlier it was necessary to have several large memory segments (for example, 1 GB), now GC supports many small segments (for example, 4 MB). GC regions provide more flexibility like repurposing regions of memory from one generation to another.

In .NET 7, regions are used by default for 64-bit applications. You can find more details in the .NET GC architect 's article.

Rate Limiting

Rate limiting is the mechanism that limits the access to a resource. You can set a certain access limit, for example, to a database.

To write a limiter in .NET 7, Microsoft added the NuGet System.Threading.RateLimiting package. Most of the work will be done with the abstract RateLimiter class. Here's one of the examples from Microsoft:

RateLimiter limiter = GetLimiter();
using RateLimitLease lease = limiter.Acquire(permitCount: 1);
if (lease.IsAcquired)
{
  // Do action that is protected by limiter
}
else
{
  // Error handling or add retry logic
}
Enter fullscreen mode Exit fullscreen mode

In this case, we are trying to get 1 permit using the Acquire method. Next comes the check – whether permit has been acquired:

  • if the permit has been acquired, we can use the resource;
  • if the permit was not acquired, this can be logged or handled as an error.

Built-in container support

Now you can quickly and easily create containerized versions of your applications using the dotnet publish command.

Example:

dotnet add package Microsoft.NET.Build.Containers
dotnet publish --os linux --arch x64 -c Release 
-p:PublishProfile=DefaultContainer
Enter fullscreen mode Exit fullscreen mode

In this case, we add a temporary link to the package to create a container and publish the project for linux x64. The result of executing the commands is an image that will be added to Docker. After that, you can launch the application using the container:

docker run -it --rm -p 5010:80 my-awesome-container-app:1.0.0
Enter fullscreen mode Exit fullscreen mode

You can read more about it here.

Performance enhancements

Performance in .NET is growing year by year. This release was no exception. It would take a separate article just to list all the improvements, so I will only tell you about the most interesting ones.

If you want to know more about the performance improvements in .NET 7, you can read about them here.

Reflection

The reflection overhead is significantly reduced when a call is made more than once for the same item (whether it is a method, constructor or property). Performance has been increased by 3-4 times.

You can read more about improvements of reflection here.

LINQ

In .NET 7, LINQ performance has been improved. For example, the efficiency of the Min and Max methods has been significantly improved when it comes to int and long arrays. This is achieved by vectorizing the processing, namely, using Vector. The results are as follows:

Image description

You can read more about LINQ performance improvements in the article.

By the way, it's also very cool that System.Linq was expended with new Order and OrderDescending methods. Previously, when using OrderBy/OrderByDescending, it was necessary to refer to its own value:

var data = new[] { 2, 1, 3 };
var sorted = data.OrderBy(x => x);
var sortedDesc = data.OrderByDescending(x => x);
Enter fullscreen mode Exit fullscreen mode

Now it is not necessary:

var data = new[] { 2, 1, 3 };
var sorted = data.Order();
var sortedDesc = data.OrderDescending();
Enter fullscreen mode Exit fullscreen mode

Regular expressions

At first, I wanted to briefly talk about improvements to regular expressions, but in the course of writing this article I realized that there were too many improvements. Therefore, let me just leave a link to a larger article dedicated to this topic :). It fully describes all the novelties and enhancements of regular expressions. I will also note here that Microsoft has not only improved performance, but also added various functional improvements.

Conclusion

As you can see, there are many improvements in .NET 7. Not all of them are equally useful to all developers, but many technologies will continue to evolve in future .NET releases.

I can single out the following features as the most interesting and useful ones for me:

  • of course, C#11;
  • on stack replacement (OSR);
  • Central package management (CPM);
  • GC Regions.

The article, of course, did not list all the new features, but only the most interesting ones (in our opinion). You can find all the improvements here.

Have you already tried any of the new .NET features? Feel free to share them in the comments.

Top comments (0)