Introduction
Oftentimes, we need a way to measure how well a piece of code does, how fast it runs, how much memory it consumes, etc. All these questions fall under the umbrella of performance measurement, and in this article, we will be looking at that.
We would be using Benchmarkdotnet
for measuring our performance. Benchmarkdotnet is a free tool that can be gotten from the NuGet repository.
The source code for this project is freely available here.
Let's get started!
Installing BenchmarkDotNet
To use benchmarkdotnet
we must first install it in our project.
Step 1: Create a new console project
Create a new console project using Visual Studio, VS code, CLI, Rider, or any preferred tool of choice. I will be using Rider for our demo.
Step 2: Install the package
Search for Benchmarkdotnet
on the NuGet repository and Install it in the newly created project.
Measuring Performance
For measuring performance, we would compare the operations of concatenating strings using the +=
operator versus using the StringBuilder
class.
Step 1: Creating our class
Create a class StringConcatenation
class with the following methods included.
public void BuildStringsWithConcatenation()
{
var output = String.Empty;
for (var i = 0; i < 100; i++)
{
output += "test";
}
}
public void BuildStringsWithStringBuilder()
{
var output = String.Empty;
var builder = new StringBuilder();
for (var i = 0; i < 100; i++)
{
builder.Append("test");
}
output = builder.ToString();
}
Step 2: Namespace inclusion
Include the BenchmarkDotNet.Attributes namespace in the StringConcatenation
class
using BenchmarkDotNet.Attributes;
Step 3: Attribute decorations
Add the [Benchmark]
attribute to each of the created methods.
Optional: You could also add the [Orderer(SummaryOrderPolicy.FastestToSlowest)]
and [MemoryDiagnoser()]
attributes to the class. The result is that the result set would be ordered from the fastest to the slowest, and the memory consumption of each method would also be included.
By the time you're done, the code should look like this:
using System.Text;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Order;
namespace BenchMark.NET;
[Orderer(SummaryOrderPolicy.FastestToSlowest)]
[MemoryDiagnoser()]
public class StringConcatenation
{
[Benchmark]
public void BuildStringsWithConcatenation()
{
var output = String.Empty;
for (var i = 0; i < 100; i++)
{
output += "test";
}
}
[Benchmark]
public void BuildStringsWithStringBuilder()
{
var output = String.Empty;
var builder = new StringBuilder();
for (var i = 0; i < 100; i++)
{
builder.Append("test");
}
output = builder.ToString();
}
}
Step 4: Bootstrapping our benchmarks
Call BenchmarkRunner.Run
In Program.cs
, add the following line of code:
using BenchMark.NET;
using BenchmarkDotNet.Running;
BenchmarkRunner.Run(typeof(StringConcatenation));
Step 5: Running the project
Run the project in Release
mode. We are not running it in Debug
mode because want our result to be as close to the production scenario as possible. On the console output, you would receive something similar to this:
Conclusion
In conclusion, we see that the BuildStringsWithStringBuilder
method completed at 628.4 ns and used 2.23 KB of memory, performing better than the BuildStringsWithConcatenation
method, which finished at 3,328.6 ns and used 41.77 KB of memory. This is expected because the StringBuilder
class presents a more effective way of building strings.