Optimizing dotnet source code using benchmarking technique using BenchmarkDotNet - Part 1
The benchmarking technique aids in calculating the performance metrics of a single or multiple sections of code in your application. Benchmark can assist you in identifying the parts of your source code that require optimization.
What's a Benchmark?
A benchmark is a basic test that delivers a set of quantifiable statistics that can assist you in determining whether or not a modification to your code has increased, decreased, or had no influence on the overall performance. It is essential to have an understanding of the performance metrics that are associated with the methods that make up your application to make use of them during the process of code optimization.
Benefits of Benchmarking a source code
- Benchmarking is the process of comparing the performance of code snippets, usually against a predefined baseline.
- Benchmarking can assist in identifying performance bottlenecks in an application. (By identifying bottlenecks, you can determine the changes needed in your source code to improve the application's performance and scalability.)
BenchmarkDotNet
BenchmarkDotNet helps you to transform methods into benchmarks, track their performance, and share reproducible measurement experiments.
This is an open-source library that can convert your.NET methods into benchmarks, monitor those methods, and gain insights into the performance data collected. It is compatible with both.NET Framework and.NET Core applications. BenchmarkDotNet can quickly convert your methods into benchmarks, run those benchmarks, and retrieve the benchmarking results. An operation in BenchmarkDotNet terminology involves executing a method decorated with the Benchmark attribute.
Steps for benchmarking code using BenchmakDotNet
To run BenchmarkDotNet in your .NET Framework or .NET Core application, you must follow these steps:
- Add the necessary NuGet package
- Add Benchmark attributes to your methods
- Create a BenchmarkRunner instance
- Run the application in Release mode
Practical
Now we can see how to config BenchmarkDotNet library in your asp.net core project and try to retrieve some measurements on the selected Scenario.
Considering Scenario - string builder vs. string performance.
To learn the BenchmarkDotNet library with the asp.net core project, a simple development scenario is utilized here.
We will compare the string builder and string in terms of performance. Here, we look at how long it takes and how much memory it takes to append 100 characters into a single string.
First, let's create a console application and install the BenchmarkDotNet NuGet package.
Create Dotnet 6 Console project and add BenchmarkDotNet library
Let’s open Visual Studio 2022 and create a .NET 6 based console application. I named it "StringBuilderVsStringBenchmarkDotnet".
This is the time to install the BenchmarkDotNet NuGet package into my console application. You can use the command given below to add the package to the console app. This command should be executed from the project directory path.
dotnet add package BenchmarkDotNet
You can also add NuGet references using Manage NuGet Packages. It will open the dialog as shown below. Search for BenchmarkDotNet
and install the package.
Note: Here, I am using Rider as my main IDE.
Benchmark Code
This is the complete code for the run benchmark methods. Here we implemented two scenarios of methods.
These couple of methods we want to benchmark. For that, we simply add [Benchmark] annotation on top of the method. It is the sign for considering to BenchmarkRunner class.
Also [MemoryDiagnoser()] annotation helps to identify memory heap of a method.
Running benchmark project
Running the benchmarking application in release configuration is a requirement for benchmarking. When building the project, you should ideally have the optimize option set to true in csproj or the CSC command line.
Additionally, the process shouldn't have a debugger attached to it. This implies that we have two choices whenever we want to run the benchmarking application.
Release mode |
- Run the application from Visual Studio/Rider by using Debug -> Start Without Debugging (keyboard shortcut CTRL + F5 ). The configuration should be set to release.
- OR the other option is to run the application using dotnet CLI. While using dotnet run command, we should ensure that we add -c release switch to the command.
dotnet run -p StringBuilderVsStringBenchmarkDotnet.csproj -c Release
Running this straightforward app might take a few seconds. This is due to BenchmarkDotNet's repeated launch of the benchmark process.
Result of the test
NOTE: Be aware that in order to perform a benchmark, we must ensure that all programs other than the benchmark process and the default OS processes are turned off. Running a benchmark while working in Visual Studio simultaneously can have a negative impact on the benchmark results.
- Mean parameter
- Allocated parameter
Conclusion
StringBuilder shows much-improved performance than the string concatenation. Average execution time and heap are also pretty low than the string concatenation.
This article does not cover all of the available features and customization options. However, it should help you get started with this package. If you want to learn more, check out their documentation.
My sample repository
Resources
I hope you find this content helpful. Keep touching my diaries. Learn something new. Comment your thoughts and share the content.
Thank you.!
Have an incredible coding journey.
See you soon. ✌✌