In recent years, everyone in IT who does anything related to the Microsoft .NET Framework knows that there is tremendous pressure to move from the “old” full .NET Framework to the new .NET Core Framework.
The pressure came initially only from Microsoft but now also from the .NET community. You can feel it, especially when you observe third-party open source projects. Slowly but steadily, they slow the development of code related to the complete .NET Framework and move to the .NET Core framework.
IdentityServer is a great example of such a third-party project. Here, for example, the latest version (4.0) only supports .NET Core. If you want to use it in the full .NET Framework, you must downgrade to version 3.0.
Trend from .NET Framework to .NET Core
The trend is therefore clear. But what is the reason?
Ok, this is a very general question. But I don’t want to try to give the full answer here. However, I think one of the main reasons is the performance gains that the .NET Framework Core offers us. This is clear when compared with the full .NET Framework.
As I will show later in this post, the gains can be very massive, ranging from 30%, up to 1200% in certain situations. Such significant performance gains cannot remain invisible.
Here is where I would like to share my findings with you.
My accidental past discovery
Ok, so here is my story on this subject.
About a year or so, I compared the speed of hashing algorithms. I had to choose the fastest one to compare the application log files.
Usage had nothing to do with security, so I considered weaker algorithms like MD5.
What I noticed was that the SHA256 algorithm was the fastest on my machine. It was much faster than SHA1 or MD5. This result made little sense, because I know that from a computer point of view, the SHA256 is much more difficult than the MD5.
This comparison is the one I made in a console application written in .NET Core 2.2. The basis of my processor in my workstation at the time was AMD Ryzen. Therefore, the test was single-threaded with the processor core number rendered irrelevant. I compared the results on an Intel-based workstation, with totally different results.
On an Intel processor, the fastest algorithm was MD5. The next instance was SHA1, then SHA256, which turned out to be the slowest. This totaled almost two or three times slower than MD5. It made me start digging for reason. What I found was that it was my workstation processor.
All AMD processors based on Zen microarchitecture (Ryzen, ThreadRipper and EPYC) are delivered with additional instructions. These extensions are called IA SHA, which most Intel-based processors simply miss. Ironically, Intel invented them.
.NET Core: developed with performance in mind
With my discovery in mind, I made the same comparison using the full .NET Framework.
The results were consistent across all processors, as SHA256 was slower than MD5 and SHA1 on AMD and Intel systems. So it was clear to me that the entire .NET Framework was not able to take advantage of the additional processor functionality.
It was the first time I discovered that the design of .NET Core had to be performance oriented. My suspicions then became reality. I then started to compare Frameworks with performance as a metric.
After that, I used the “BenchmarkDotNet” v12 library in a simple console application to test some heavy operations between frameworks. I also did this between different CPU architectures to find the differences. Thanks to this library, test and report statistics were generated automatically.
Here is the list of operations that were put into the test (the test was single-threaded):
- EnumParse – parsing the string value to an enum value
- LinqOrderBySkipFirst – ordering the reversed sequence of ten million integers, skipping 4 of them and then choosing the first element
- Sha256 – computing the SHA256 hash of the 100MB array
- StringStartsWith – checking if the string “abcdefghijklmnopqrstuvwxyz” begins with a “abcdefghijklmnopqrstuvwxy-” value (repeated 100,000,000 times)
- Deserialize – creating, serializing and deserializing a list of 100,000 objects (each containing two string properties holding an integer value) using BinaryFormatter.
.NET Core vs .NET Framework: Conclusions
After analyzing the results and my experience with the two frameworks, I came to the following conclusions:
The full .NET Framework is not able to exploit the full potential of the operating platform. It ignored the additional processor instructions available, such as the IA SHA extensions mentioned above.
.NET Core was in all of my tests much faster than full .NET – sometimes 7 or even up to 13 times faster.
Choosing the right processor architecture can dramatically change the behavior of your application, so the results collected from one architecture may be invalid for the other and vice versa. For example – if your .NET Core application performs a lot of SHA256 hash calculations, the best option would be to use servers based on AMD Zen instead of those based on Intel.
So to sum up – if performance is a big factor in your application, you should opt for .NET Core vs .NET Framework.
Please note, that tests showed here focused only on Framework performance itself (there were almost no I/O operations involved like database access, file access or network access).
So, if your application is highly I/O dependent, then beware that you can see little to no gains from choosing the .NET Core vs .NET Framework.