navigation

Key performance changes in .NET Core 7: an overview

Key performance changes in .NET Core 7: an overview

by
December 5, 2022
.NET, Tech
No Comment

With .NET Core 7 already here, you’re probably wondering what to expect from Microsoft’s new framework. 

Let’s find out. 

I started by creating and running an empty Web API project. I saw that .NET Core 7 requires around 40% less memory than its predecessor. To be honest, I was surprised. It took me back in time to when apps were less resource intensive. This is going to change prices in the cloud a bit, offload all the docker pods – and many more wonderful things. 

Having seen this, I couldn’t wait to find out more about the other changes and new features. 

In this article, I’m going to tell you about them and explain which ones I believe are important. 

.Net Release Cycle & Support Policy

Ever since .NET Core 5, Microsoft has announced they’d be releasing a new version yearly.

  • LTS – Long-Term Support
  • STS – Short-Term Support

The even and odd version numbers have different support periods. As you can see, 6 and 8 are LTS versions, and they get 3 years of support. Versions 5 and 7 get around 18 months. By doing that, they’re giving us 6 months to update our application to the next version. 

Talking about updates, Microsoft has a tool that can help you migrate your app from .NET Framework – to .NET Core 6, for example. You can find the open-source code in this GitHub repository.

So this November, we’re waiting for the .NET Core 7 version. I was really impressed when I saw all the improvements it has to offer. Let’s go over them and dig into a few specific ones.

Reflection

As you already know, Reflection is a way to obtain information about already loaded assemblies and their type definitions. Most people have mixed feelings about this technology. As usual, the truth is in the middle.

If you aren’t familiar with it, I recommend you read Microsoft’s post on the topic before using it. For now, let’ compare the most widely used reflection methods and their behavior between .NET Core 6 and 7.

MethodRuntimeMeanRatio
MethodInvoke.NET 6.043.846 ns1.00
MethodInvoke.NET 7.08.078 ns0.18
GetUnderlyingType.NET 6.027.413 ns1.00
GetUnderlyingType.NET 7.05.115 ns0.19
CreateInstance.NET 6.03.827 ns1.00
CreateInstance.NET 7.02.276 ns0.60
IsByRefLike.NET 6.02.1322 ns1.000
IsByRefLike.NET 7.00.0000 ns0.000

Arrays and Strings

From my experience working in a custom software development company, I can say that .NET 7 introduces a lot of APIs, which helps us to write more optimized code. 

The first useful API which we will look at is MemoryExtension.CommonPrefixLength. It returns the number of elements that are the same at the beginning of each input. 

Other new APIs include the IndexOf variants: IndexOfAnyExcept and LastIndexOfAnyExcept. They do exactly what their names suggest. Of course, you can write your own methods for checking the elements in an array, but they won’t be so optimized. I`ll paste the Stephen Toub code samples below to show you how fast and useful the new methods are.

MethodMeanRatio
OpenCoded370.47 ns1.00
IndexOfAnyExcept23.84 ns0.06

I have good news for you. This new version also comes with changes in IndexOf and LastIndexOf. There are a lot of performance optimizations there, so it’s going to affect and improve the existing code, as well. 

For example, let’s search for the word ‘elementary’ in a text using indexOf. In the 6th version it’s going to take 1,063.67 us, compared to version 7 it’s going to take 56.04 us. It’s around 19 times faster than before. 

Let me show you some of the improved parts of StringBuilder. I was really impressed with the fact that they’ve changed the StringBuilder Replace method logic. Now it’s using IndexOf under the hood. The performance is, again, excellent – more than 20-fold improvement. AppendFormat, Append, and other functions have had many changes, but I won’t get into all of them here. 

LINQ

Microsoft has been analyzing a lot of real-world scenarios for use of Enumerable.Min and Max functions. The results show they’re mostly used with arrays. 

So now the functions check if the collection is an array. If it is, they execute the newly created implementation with Vector<T>. If not, then they continue with the old one. This check decreases the processing time when we’re working with an inappropriate collection(HashSet) because of these checks – but maybe this is going to be fixed in the next version. Also, the memory allocation in the newest version is 0. If we compare that to .NET 6, the memory there is 32B. 

HashSet results:

C# 11

Finally, we can format our string text however we want with the newly created string interpolations.

“””

As you can see

We can format our lines just like that

They just need to be wrapped in a (“””). 

If the string, for example, contains “”” , your interpolation has to start with one more double quote char

“””

There is one more wonderful thing. We can use switch statements in our string interpolations.

List patterns are the second interesting thing. I’m not sure how often we are going to use this feature but it looks good.

Auto-default struct initialization is another good thing that can save some unnecessary code.

If we have a parameterless constructor the new version of c# is going to set default values to all properties.

A new way to create UTF-8 String literals for better productivity, resiliency and performance. When you add ‘u8’ to the string, this forces the type to be UTF-8. Ex: “example”u8.

Conclusion

More than 1000 PRs were merged into .NET Core 7. All the optimisations and improvements are simply too numerous to be described here. Every .NET Core version is getting better and better. I love the Microsoft migration strategy because every application is going to be migrated soon or later. Do not forget to review all the breaking changes before updating. Happy coding : )

Do you want more great blogs like this?

Subscribe for Dreamix Blog now!