Jeremy Lindsay

.net, .net core, Non-functional Requirements, Performance

Using async/await and Task.WhenAll to improve the overall speed of your C# code

Recently I’ve been looking at ways to improve the performance of some .NET code, and this post is about an async/await pattern that I’ve observed a few times that I’ve been able to refactor.

Every-so-often, I see code like the sample below – a single method or service which awaits the outputs of numerous methods which are marked as asynchronous.

await FirstMethodAsync();
 
await SecondMethodAsync();
 
await ThirdMethodAsync();

The three methods don’t seem to depend on each other in any way, and since they’re all asynchronous methods, it’s possible to run them in parallel. But for some reason, the implementation is to run all three synchronously – the flow of execution awaits the first method running and completing, then the second, and then the third.

We might be able to do better than this.

Let’s look at an example

For this post, I’ve created a couple of sample methods which can be run asynchronously – they’re called SlowAndComplexSumAsync and SlowAndComplexWordAsync.

What these methods actually do isn’t important, so don’t worry about what function they serve – I’ve just contrived them to do something and be quite slow, so I can observe how my code’s overall performance alters as I do some refactoring.

First, SlowAndComplexSumAsync (below) adds a few numbers together, with some artificial delays to deliberately slow it down – this takes about 2.5s to run.

private static async Task<int> SlowAndComplexSumAsync()
{
    int sum = 0;
    foreach (var counter in Enumerable.Range(0, 25))
    {
        sum += counter;
        await Task.Delay(100);
    }
 
    return sum;
}

Next SlowAndComplexWordAsync (below) concatenates characters together, again with some artificial delays to slow it down. This method usually about 4s to run.

private static async Task<string> SlowAndComplexWordAsync()
{
    var word = string.Empty;
    foreach (var counter in Enumerable.Range(65, 26))
    {
        word = string.Concat(word, (char) counter);
        await Task.Delay(150);
    }
 
    return word;
}

Running synchronously – the slow way

Obviously I can just prefix each method with the “await” keyword in a Main method marked with the async keyword, as shown below. This code basically just runs the two sample methods synchronously (despite the async/await cruft in the code).

private static async Task Main(string[] args)
{
    var stopwatch = new Stopwatch();
    stopwatch.Start();
 
    // This method takes about 2.5s to run
    var complexSum = await SlowAndComplexSumAsync();
 
    // The elapsed time will be approximately 2.5s so far
    Console.WriteLine("Time elapsed when sum completes..." + stopwatch.Elapsed);
 
    // This method takes about 4s to run
    var complexWord = await SlowAndComplexWordAsync();
    
    // The elapsed time at this point will be about 6.5s
    Console.WriteLine("Time elapsed when both complete..." + stopwatch.Elapsed);
    
    // These lines are to prove the outputs are as expected,
    // i.e. 300 for the complex sum and "ABC...XYZ" for the complex word
    Console.WriteLine("Result of complex sum = " + complexSum);
    Console.WriteLine("Result of complex letter processing " + complexWord);
 
    Console.Read();
}

When I run this code, the console output looks like the image below:

series

As can be seen in the console output, both methods run consecutively – the first one takes a bit over 2.5s, and then the second method runs (taking a bit over 4s), causing the total running time to be just under 7s (which is pretty close to the predicted duration of 6.5s).

Running asynchronously – the faster way

But I’ve missed a great opportunity to make this program run faster. Instead of running each method and waiting for it to complete before starting the next one, I can start them all together and await the Task.WhenAll method to make sure all methods are completed before proceeding to the rest of the program.

This technique is shown in the code below.

private static async Task Main(string[] args)
{
    var stopwatch = new Stopwatch();
    stopwatch.Start();
 
    // this task will take about 2.5s to complete
    var sumTask = SlowAndComplexSumAsync();
 
    // this task will take about 4s to complete
    var wordTask = SlowAndComplexWordAsync();
 
    // running them in parallel should take about 4s to complete
    await Task.WhenAll(sumTask, wordTask);

    // The elapsed time at this point will only be about 4s
    Console.WriteLine("Time elapsed when both complete..." + stopwatch.Elapsed);
 
    // These lines are to prove the outputs are as expected,
    // i.e. 300 for the complex sum and "ABC...XYZ" for the complex word
    Console.WriteLine("Result of complex sum = " + sumTask.Result);
    Console.WriteLine("Result of complex letter processing " + wordTask.Result);
 
    Console.Read();
}

And the outputs are shown in the image below.

parallel

The total running time is now only a bit over 4s – and this is way better than the previous time of around 7s. This is because we are running both methods in parallel, and making full use of the opportunity asynchronous methods present. Now our total execution time is only as slow as the slowest method, rather than being the cumulative time for all methods executing one after each other.

Wrapping up

I hope this post has helped shine a little light on how to use the async/await keywords and how to use Task.WhenAll to run independent methods in parallel.

Obviously every case has its own merits – but if code has series of asynchronous methods written so that each one has to wait for the previous one to complete, definitely check out whether the code can be refactored to use Task.WhenAll to improve the overall speed.

And maybe even more importantly, when designing an API surface, keep in mind that decoupling dependencies between methods might give developers using the API an opportunity to run these asynchronous methods in parallel.


About me: I regularly post about Microsoft technologies and .NET – if you’re interested, please follow me on Twitter, or have a look at my previous posts here. Thanks!

.net, Cake, Performance

Calling a custom executable from Cake using StartProcess and ProcessSettings

I’ve previously written about how I’ve used Cake to orchestrate my build and deployment processes, and write the code for these processes in C# rather than PowerShell. This time I’ll write about how I’ve improved the speed of my deployment process by using custom tools which aren’t yet built into Cake.

Some background about my deployment process

A common part of a deployment process is copying files repetitively from a source to a destination, and Cake provides a good way to do this – the CopyFiles static method.

To use this, we just need to specify the source directory, the remote destination directory, and plug these in as parameters. I’ve written some sample code below showing how a “Deploy” task might move an application from a “publish” directory to a remote machine.

Task("Deploy")
    .Does(() =>
    {
	// The files I want to copy are in the publish directory - I use the
	// wildcard character to specify that I want to copy everything
	var source = @".\publish\*";
 
	// The destination is on my local network and accessible on the path below
	var destination = @"\\192.168.1.125\c$\ConsoleApps\DeployedApplication";
 
	// Now just plug in the source, destination
	// The boolean parameter ensures we preserve the folder structure
	CopyFiles(source, destination, true);
    });

This works well, but it also copies across every file, every time – it doesn’t matter whether the file has changed or not – and this the slowest part of my deployment process.  I would prefer to mirror my source and destination files, and only copy across files that have changed. This would speed up deployments across my local network.

Using RoboCopy to mirror directory structures

Microsoft have created a command line file copy utility which allows me to copy or mirror directory structures called RoboCopy (Robust File Copy) – it’ll only copy the files/directories that have changed, and this sounds like exactly what I need.

In copying files from source to destination, I’ve chosen the word “mirror” because RoboCopy needs to be passed a switch “/MIR”, which is short for mirror. From Microsoft’s TechNet documentation:

/MIR is an option to ROBOCOPY where you mirror a directory tree with all the subfolders including the empty directories and you purge files and folders on the destination server that no longer exists in source.

The command I’d need to mirror files has the format:

robocopy /MIR source_directory destination_directory

And to copy from my source directory

".\publish\"

to the destination on the C drive of a machine with IP address 192.168.1.125:

"\ConsoleApps\DeployedApplication"

I just need to plug these values as arguments to the robocopy executable, as shown below:

robocopy /MIR ".\publish\" "\\192.168.1.125\c$\ConsoleApps\DeployedApplication"

But how can I use RoboCopy with Cake?

Turns out it’s quite easy with a few things in Cake which can help us.

  • We can use the StartProcess method – I can pass in executable that I want to run (i.e. robocopy.exe), and I can also pass in the arguments for this executable.

I don’t need to pass in the full path to the executable because robocopy.exe is in a folder which is in my machine’s path, i.e. C:\Windows\System32

  • I can also clean up my code a little by keeping this code in its own method in the Cake.build file.
private void MirrorFiles(string source, string destination)
{
    StartProcess("robocopy", new ProcessSettings {
        Arguments = new ProcessArgumentBuilder()
            .Append(@"/MIR")
            .Append(source)
            .Append(destination)
        }
    );
}

Now I can adjust the Task shown previously (i.e. “Deploy”) to use this method instead:

Task("Deploy")
    .Does(() =>
    {
	// The files I want to copy are in the publish directory
	var source = @".\publish\";
 
	// The destination is on my local network and accessible on the path below
	var destination = @"\\192.168.1.125\c$\ConsoleApps\DeployedApplication";
 
	// Now just plug in the source, destination
	MirrorFiles(source, destination);
    }

What practical difference does this make?

In my application’s Cake build script, there’s very little difference – a new method to mirror files, and a slight change to a task to copy (or mirror) files across a network.

But the real advantage comes when we look at the time taken to deploy my application.

Another nice feature of Cake is that it writes out the time taken by each task which helps with performance benchmarking.

I’ve pasted the timings for each stage of my original deployment process below for when I just copy files instead of using robocopy:

Task                  Duration 
--------------------------------------------------
Clean                 00:00:00.2378497 
Restore               00:00:03.9107662 
Build                 00:00:05.2128133 
Publish               00:00:08.0715728 
Deploy                00:00:43.1527382 
Default               00:00:00.0021827 
--------------------------------------------------
Total:                00:01:00.5879229

Notice it took 43 seconds to deploy my application’s files from source to destination – approximately 75% of the total time. And everytime I change my application and re-deploy, the time taken to carry out this operation is approximately the same, copying across files that have changed and also those that haven’t changed.

Let’s change the script to mirror files using robocopy (i.e. only copy across files that have changed since the last build) rather than just copying all files – I’ve pasted the new timings below:

Task                  Duration 
--------------------------------------------------
Clean                 00:00:00.2661543 
Restore               00:00:02.7529030 
Build                 00:00:04.7478403 
Publish               00:00:06.3981560 
Deploy                00:00:00.6685282 
Default               00:00:00.0033186 
--------------------------------------------------
Total:                00:00:14.8369004

It has gone from copying every file in 43 seconds to just copying 5 files that changed in 0.66 seconds – this is a huge difference for me, making it much quicker and more convenient for me to make an application, change, build and deploy to my test rig.

Wrapping up

In this post I wanted to share with the community how flexible Cake is by demonstrating how I’ve used Robocopy to speed my up deployments.

  • I’ve been able to switch out Cake’s built in copying feature, and instead use a local executable (that isn’t a core part of Cake or an addin) by passing it to the StartProcess method.
  • I’ve been able to write a private method in my C# Cake.build script to keep the code clean.
  • Finally I’ve been able to use Cake’s default output to benchmark performance before and after my change.

Being able to extend the core features in Cake with StartProcess is really powerful – it’s not quite as re-useable as building a dedicated add-in, but it can still allow us to quickly customise and optimise build scripts.


About me: I regularly post about .NET – if you’re interested, please follow me on Twitter, or have a look at my previous posts here. Thanks!

.net, Non-functional Requirements, Performance

Measuring your code’s performance during development with BenchmarkDotNet – Part #2: Methods with parameters

Last time, I wrote about how to use BenchmarkDotNet (Github here: NuGet: here) to measure code performance for a very simple method with no parameters. This time I’ll write about testing another scenario that I find is more common – methods with parameters.

Let’s start with a simple case – primitive parameters.

Methods with Primitive Parameters

Let’s write a method which takes an integer parameter and calculates the square.

I know that I could use the static System.Math.Pow(int a, int b) for this instead of rolling my own method – but more on this later.

I written a little static method like this.

public class MathFunctions
{
    public static long Square(int number)
    {
        return number * number;
    }
}

Nothing wrong with that – but not that easy to test with BenchmarkDotNet and decorate with a simple [Benchmark] attribute because I need to specify the number parameter.

There are a couple of ways to test this.

Refactor and use the Params attribute

Instead of passing the number as a parameter to the Square method, I can refactor the code so that Number is a property of the class, and the Square method uses this property.

public class MathFunctions
{
    public int Number { getset; }
 
    public long Square()
    {
        return this.Number * this.Number;
    }
}

Now I can decorate Square method with the [Benchmark] attribute, and I can use the ParamsAttribute in BenchmarkDotNet to decorate the property with numbers that I want to test.

public class MathFunctions
{
    [Params(12)]
    public int Number { getset; }
        
    [Benchmark]
    public int Square()
    {
        return this.Number * this.Number;
    }
}

And then it’s very simple to execute a performance runner class like the code below:

using BenchmarkDotNet.Running;
using Services;
 
namespace PerformanceRunner
{
    class Program
    {
        static void Main(string[] args)
        {
            var summary = BenchmarkRunner.Run<MathFunctions>();
        }
    }
}

Which yields the results:

// * Summary *

BenchmarkDotNet=v0.10.8, OS=Windows 10 Redstone 2 (10.0.15063)
Processor=Intel Core i7-2640M CPU 2.80GHz (Sandy Bridge), ProcessorCount=4
Frequency=2728178 Hz, Resolution=366.5450 ns, Timer=TSC
dotnet cli version=2.0.0-preview2-006127
 [Host] : .NET Core 4.6.25316.03, 64bit RyuJIT
 DefaultJob : .NET Core 4.6.25316.03, 64bit RyuJIT


 Method | Number | Mean      | Error     | StdDev    | Median    |
------- |------- |----------:|----------:|----------:|----------:|
 Square | 1      | 0.0429 ns | 0.0370 ns | 0.0658 ns | 0.0001 ns |
 Square | 2      | 0.0035 ns | 0.0086 ns | 0.0072 ns | 0.0000 ns |

This mechanism has the advantage that you can specify a range of parameters and observe the behaviour for each of the values.

But I think it has a few disadvantages:

  • I’m a bit limited in the type of parameter that I can specify in an attribute. Primitives like integers and strings are easy, but instantiating a more complex data transfer object is harder.
  • I have to refactor my code to measure performance – you could argue that the refactored version is better code, but to me the code below is simple and has a clear intent:
var output = MathFunctions.Square(10);

Whereas I think the code below is more obtuse.

var math = new MathFunctions { Number = 10 };
var output = math.Square();
  • My source code has a tight dependency on the BenchmarkDotNet library, and the attributes add a little litter to the class.

Basically I’m not sure I’ve made my code better by refactoring it to measure performance. Let’s look at other techniques.

Separate performance measurement code into a specific test class

I can avoid some of the disadvantages of the technique above by creating a dedicated class to measure the performance of my method, as shown below.

public class MathFunctions
{
    public static long Square(int number)
    {
        return number * number;
    }
}
 
public class PerformanceTestMathFunctions
{
    [Params(12)]
    public int Number { getset; }
 
    [Benchmark]
    public long Measure_Speed_of_Square_Function()
    {
        return MathFunctions.Square(Number);
    }
}

So now I can run the code below to measure the performance of my method.

using BenchmarkDotNet.Running;
using Services;
 
namespace PerformanceRunner
{
    class Program
    {
        static void Main(string[] args)
        {
            var summary = BenchmarkRunner.Run<PerformanceTestMathFunctions>();
        }
    }
}

This time I’ve not had to refactor my original code, and I’ve moved the dependency from my source code under test to the dedicated test class. But I’m still a bit limited in what types of parameter I can supply to my test class.

Using GlobalSetup for methods with non-primitive data transfer object parameters

Let’s try benchmarking an example which is a bit more involved – how to measure the performance of some more math functions I’ve written which use Complex Numbers.

Complex numbers are nothing to do with BenchmarkDotNet – I’m just using this as an example of a non-trivial problem space and how to run benchmark tests against it.

At school you might have done some work with Complex Numbers. These numbers have a real and imaginary component – which sounds weird if you’re not used to it, but they can be represented as:

1 + 2i

Where 1 is the real component, and 2 is the size of the ‘imaginary’ component.

If you want to calculate the magnitude of a complex number, you just use Pythagorean maths – namely:

  • Calculate the square of the real component, and the square of the imaginary component.
  • Add these two squares together.
  • The magnitude is the square root of the sum of the two squares.

So I can represent a Complex Number in code in the object class shown below:

public class ComplexNumber
{
    public int Real { getset; }
 
    public int Imaginary { getset; }
}

And I can instantiate a complex number 1 + 2i with the code:

new ComplexNumber { Real = 1, Imaginary = 2 };

If I want to calculate the magnitude of this Complex Number, I can pass the ComplexNumber data transfer object as a parameter to a method shown below.

public class ComplexMathFunctions
{
    public static double Magnitude(ComplexNumber complexNumber)
    {
        return Math.Pow(Math.Pow(complexNumber.Real, 2                        + Math.Pow(complexNumber.Imaginary, 2), 0.5);
    }
}

But how do I benchmark this?

I can’t instantiate a ComplexNumber parameter in the Params attribute supplied by BenchmarkDotNet.

Fortunately there’s a GlobalSetup attribute – this is very similar to the Setup attribute used by some unit test frameworks, were we can arrange our parameters before they are used by a test.

The code below shows how to create a dedicated test class, and instantiate a Complex Number in the GlobalSetup method which is used in the method being benchmarked.

public class PerformanceTestComplexMathFunctions
{
    private ComplexNumber ComplexNumber;
 
    [GlobalSetup]
    public void GlobalSetup()
    {
        this.ComplexNumber = new ComplexNumber { Real = 1, Imaginary = 2 };
    }
 
    [Benchmark]
    public double Measure_Magnitude_of_ComplexNumber_Function()
    {
        return ComplexMathFunctions.Magnitude(ComplexNumber);
    }
}

This yields the results below:

// * Summary *

BenchmarkDotNet=v0.10.8, OS=Windows 10 Redstone 2 (10.0.15063)
Processor=Intel Core i7-2640M CPU 2.80GHz (Sandy Bridge), ProcessorCount=4
Frequency=2728178 Hz, Resolution=366.5450 ns, Timer=TSC
dotnet cli version=2.0.0-preview2-006127
 [Host] : .NET Core 4.6.25316.03, 64bit RyuJIT
 DefaultJob : .NET Core 4.6.25316.03, 64bit RyuJIT


 Method                                      | Mean     | Error    | StdDev    |
-------------------------------------------- |---------:|---------:|----------:|
 Measure_Magnitude_of_ComplexNumber_Function | 110.5 ns | 1.058 ns | 0.9897 ns |

I think this eliminates pretty much all the disadvantages I listed earlier, but does add a restriction that I’m only testing one instantiated value of the data transfer object parameter.

You might wonder why we need the GlobalSetup at all when we could just instantiate a local variable in the method under test – I don’t think we should do that because we’d also be including the time taken to set up the experiment in the method being benchmarked – which reduces the accuracy of the measurement.

Addendum

I was kind of taken aback by how slow my Magnitude function was, so I started playing with some different options – instead of using the built in System.Math.Pow static method, I decide to calculate a square by just multiplying the base by itself. I also decided to use the System.Math.Sqrt function to calculate the square root, rather than the equivalent of raising the base to the power of 0.5. My refactored code is shown in the code below.

public class ComplexMathFunctions
{
    public static double Magnitude(ComplexNumber complexNumber)
    {
        return Math.Sqrt(complexNumber.Real * complexNumber.Real 
                    + complexNumber.Imaginary * complexNumber.Imaginary);
    }
}

Re-running the test yielded the benchmark results below:

// * Summary *

BenchmarkDotNet=v0.10.8, OS=Windows 10 Redstone 2 (10.0.15063)
Processor=Intel Core i7-2640M CPU 2.80GHz (Sandy Bridge), ProcessorCount=4
Frequency=2728178 Hz, Resolution=366.5450 ns, Timer=TSC
dotnet cli version=2.0.0-preview2-006127
 [Host] : .NET Core 4.6.25316.03, 64bit RyuJIT
 DefaultJob : .NET Core 4.6.25316.03, 64bit RyuJIT


 Method                                      | Mean     | Error     | StdDev    |
-------------------------------------------- |---------:|----------:|----------:|
 Measure_Magnitude_of_ComplexNumber_Function | 4.192 ns | 0.0371 ns | 0.0347 ns |

So with a minor code tweak, the time taken to calculate the magnitude dropped from 110.5 nanoseconds to 4.192 nanoseconds. That’s a pretty big performance improvement. If I hadn’t been measuring this, I’d probably never have known that I could have improved my original implementation so much.

Of course, this performance improvement might only work for small integers – it could be that large integers have a different performance profile. But it’s easy to understand how we could set up some other tests to check this.

Wrapping up

This time I’ve written about how to use BenchmarkDotNet to measure the performance of methods which have parameters, even ones that are data transfer objects. The Params attribute can be useful sometimes for methods which have simple primitive parameters, and the GlobalSetup attribute can specify a method which sets up more complicated scenarios. I’ve also shown how we can create classes dedicated to testing individual methods, and keep benchmarking test references isolated in their own classes and projects.

This makes it really simple to benchmark your existing codebase, even code which wasn’t originally designed with performance testing in mind. I think it’s worth doing – even while writing this post, I unexpectedly discovered a simple way to change my example code that made a big performance improvement.

I hope you find this post useful in starting to measure the performance of your codebase. If you want to dig into understanding BenchmarkDotNet more, I highly recommend this post from Andrey Akinshin – it goes into lots more detail.


About me: I regularly post about .NET – if you’re interested, please follow me on Twitter, or have a look at my previous posts here. Thanks!

.net, Non-functional Requirements, Performance

Measuring your code’s performance during development with BenchmarkDotNet – Part #1: Getting started

I was inspired to write a couple of posts after recently reading articles by Stephen Toub and Andrey Akinshin about BenchmarkDotNet from the .NET Blog, and I wanted to write about how I could use BenchmarkDotNet to understand my own existing codebase a little bit better.

A common programming challenge is how to manage complexity around code performance – a small change might have a large impact on application performance.

I’ve managed this in the past with page-level performance tests (usually written in JMeter) running on my integration server – and it works well.

However, these page-level performance tests only give me coarse grained results – if the outputs of the JMeter tests start showing a slowdown, I’ll have to do more digging in the code to find the problem. At this point, tools like ANTS or dotTrace are really good for finding the bottlenecks – but even with these, I’m reacting to a problem rather than managing it early.

I’d like to have more immediate feedback – I’d like to be able to perform micro-benchmarks against my code before and after I make small changes, and know right away if I’ve made things better or worse. Fortunately BenchmarkDotNet helps with this.

This isn’t premature optimisation – this is about how I can have a deeper understanding of the quality of code I’ve written. Also, if you don’t know if your code is slow or not, how can you argue that any optimisation is premature?

A simple example

Let’s take a simple example – say that I have a .NET Core website which has a single page that just generates random numbers.

Obviously this application wouldn’t be a lot of use – I’m deliberately choosing something conceptually simple so I can focus on the benchmarking aspects.

I’ve created a simple HomeController, which has an action called Index that returns a random number. This random number is generated from a service called RandomNumberGenerator.

Let’s look at the source for this. I’ve put the code for the controller below – this uses .NET Core’s built in dependency injection feature.

using Microsoft.AspNetCore.Mvc;
using Services;
 
namespace SampleFrameworkWebApp.Controllers
{
    public class HomeController : Controller
    {
        private readonly IRandomNumberGenerator _randomNumberGenerator;
        
        public HomeController(IRandomNumberGenerator randomNumberGenerator)
        {
            _randomNumberGenerator = randomNumberGenerator;
        }
 
        public IActionResult Index()
        {
            ViewData["randomNumber"= _randomNumberGenerator.GetRandomNumber();
 
            return View();
        }
    }
}

The code below shows the RandomNumberGenerator – it uses the Random() class from the System library.

using System;
 
namespace Services
{
    public class RandomNumberGenerator : IRandomNumberGenerator
    {
        private static Random random = new Random();
 
        public int GetRandomNumber()
        {
            return random.Next();
        }
    }
}

A challenge to make it “better”

But after a review, let’s say a colleague tells me that the System.Random class isn’t really random – it’s really only pseudo random, certainly not random enough for any kind of cryptographic purpose. If I want to have a really random number, I need to use the RNGCryptoServiceProvider class.

So I’m keen to make my code “better” – or at least make the output more cryptographically secure – but I’m nervous that this new class is going to make my RandomNumberGenerator class slower for my users. How can I measure the before and after performance without recording a JMeter test?

Using BenchmarkDotNet

With BenchmarkDotNet, I can just decorate the method being examined using the [Benchmark] attribute, and use this to measure the performance of my code as it is at the moment.

To make this attribute available in my Service project, I need to include a nuget package in my project, and you can use the code below at the Package Manager Console:

Install-Package BenchmarkDotNet

The code for the RandomNumberGenerator class now looks like the code below – as you can see, it’s not changed much at all – just an extra library reference at the top, and a single attribute decorating the method I want to test.

using System;
using BenchmarkDotNet.Attributes;
 
namespace Services
{
    public class RandomNumberGenerator : IRandomNumberGenerator
    {
        private static Random random = new Random();
 
        [Benchmark]
        public int GetRandomNumber()
        {
            return random.Next();
        }
    }
}

I like to keep my performance benchmarking code in a separate project (in the same way that I keep my unit tests in a separate project). That project is a simple console application, with a main class that looks like the code below (obviously I need to install the BenchmarkDotNet nuget package in this project as well):

using BenchmarkDotNet.Running;
using Services;
 
namespace PerformanceRunner
{
    class Program
    {
        static void Main(string[] args)
        {
            var summary = BenchmarkRunner.Run<RandomNumberGenerator>();
        }
    }
}

And now if I run this console application at a command line, BenchmarkDotNet presents me with some experiment results like the ones below.

// * Summary *

BenchmarkDotNet=v0.10.8, OS=Windows 10 Redstone 2 (10.0.15063)
Processor=Intel Core i7-2640M CPU 2.80GHz (Sandy Bridge), ProcessorCount=4
Frequency=2728183 Hz, Resolution=366.5443 ns, Timer=TSC
dotnet cli version=2.0.0-preview2-006127
 [Host] : .NET Core 4.6.25316.03, 64bit RyuJIT
 DefaultJob : .NET Core 4.6.25316.03, 64bit RyuJIT


          Method | Mean     | Error     | StdDev    |
---------------- |---------:|----------:|----------:|
 GetRandomNumber | 10.41 ns | 0.0468 ns | 0.0365 ns |

As you can see above, my machine specifications are listed, and the experiment results suggest that my RandomNumberGenerator class presently takes about 10.41 nanoseconds to generate a random number.

So now I have a baseline – after I change my code to use the more cryptographically secure RNGCryptoServiceProvider, I’ll be able to run this test again and see if I’ve made it faster or slower.

How fast is the service after the code changes?

I’ve changed the service to use the RNGCryptoServiceProvider – the code is below.

using System;
using BenchmarkDotNet.Attributes;
using System.Security.Cryptography;
 
namespace Services
{
    public class RandomNumberGenerator : IRandomNumberGenerator
    {
        private static Random random = new Random();
 
        [Benchmark]
        public int GetRandomNumber()
        {
            using (var randomNumberProvider = new RNGCryptoServiceProvider())
            {
                byte[] randomBytes = new byte[sizeof(Int32)];
 
                randomNumberProvider.GetBytes(randomBytes);
 
                return BitConverter.ToInt32(randomBytes, 0);
            }
        }
    }
}

And now, when I run the same performance test at the console, I get the results below. The code has become slower, and now takes 154.4 nanoseconds instead of 10.41 nanoseconds.

BenchmarkDotNet=v0.10.8, OS=Windows 10 Redstone 2 (10.0.15063)
Processor=Intel Core i7-2640M CPU 2.80GHz (Sandy Bridge), ProcessorCount=4
Frequency=2728183 Hz, Resolution=366.5443 ns, Timer=TSC
dotnet cli version=2.0.0-preview2-006127
 [Host] : .NET Core 4.6.25316.03, 64bit RyuJIT
 DefaultJob : .NET Core 4.6.25316.03, 64bit RyuJIT


          Method | Mean     | Error    | StdDev   |
---------------- |---------:|---------:|---------:|
 GetRandomNumber | 154.4 ns | 2.598 ns | 2.028 ns |

So it’s more functionally correct, and unfortunately it has become a little slower. But I can now go to my technical architect with a proposal to change the code, and present a more complete picture – they’ll be able to not only understand why my proposed code is more cryptographically secure, but also I’ll be able to show some solid metrics around the performance deterioration cost. With this data, they have can make better decisions about what mitigations they might want to put in place.

How should I use these numbers?

A slow down from about 10 to 150 nanoseconds doesn’t mean that the user’s experience deteriorates by a factor of 15 – remember that in this case, a single user’s experience is over the entire lifecycle of the page, so really a single user should only see a slowdown of 140 nanoseconds over the time it takes to refresh the whole page. Obviously a website will have many more users than just one at a time, and this is where our JMeter tests will be able to tell us more accurately how the page performance deteriorates at scales of hundreds or thousands of users.

Wrapping up

BenchmarkDotNet is a great open-source tool (sponsored by the .NET Foundation) that allows us to perform micro-benchmarking experiments on methods in our code. Check out more of the documentation here.

I’ve chosen to demonstrate BenchmarkDotNet with a very small service that has methods which take no parameters. The chances are that your code is more complex than this example, and you can structure your code to so that you can pass parameters to BenchmarkDotNet – I’ll write more about these more complicated scenarios in the next post.

Where I think BenchmarkDotNet is most valuable is that it changes the discussion in development teams around performance. Rather than changing code and hoping for the best – or worse, reacting to an unexpected performance drop affecting users – micro-benchmarking is part of the development process, and helps developers understand and mitigate code problems before they’re even pushed to an integration server.


About me: I regularly post about .NET – if you’re interested, please follow me on Twitter, or have a look at my previous posts here. Thanks!

.net core, C# tip, MVC, Non-functional Requirements, Performance

Creating a RESTful Web API template in .NET Core 1.1 – Part #3: Improving the performance by using compression

One of the simplest and most effective improvements you can make to your website or web service is to compress the stream of data sent from the server. With .NET Core 1.1, it’s really simple to set this up – I’ve decided to include this in my template project, but the instructions below will work for any .NET Core MVC or Web API project.

Only really ancient browsers are going to have problems with gzip – I’m pretty happy to switch it on by default.

.NET Core 1.1 adds compression to the ASP.NET HTTP pipeline using some middleware in the Microsoft.AspNetCore.ResponseCompression package. Let’s look at how to add this to our .NET Core Web API project.

Step 1: Add the Microsoft.AspNetCore.ResponseCompression package

There’s a few different ways to do this – I prefer to add packages from within PowerShell. From within Visual Studio (with my project open), I open a Package Manager Console, and run:

Install-Package Microsoft.AspNetCore.ResponseCompression

(But it’s obviously possible to do this from within the NuGet package manager UI as well)

This will add the package to the Web API project, and you can see this in the project.json file (partially shown below).

{
  "dependencies": {
    "Microsoft.NETCore.App": {
      "version": "1.1.0",
      "type": "platform"
    },
    "Microsoft.AspNetCore.Mvc": "1.1.0",
    "Microsoft.AspNetCore.Routing": "1.1.0",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
    "Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
    "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0",
    "Microsoft.Extensions.Configuration.FileExtensions": "1.1.0",
    "Microsoft.Extensions.Configuration.Json": "1.1.0",
    "Microsoft.Extensions.Logging": "1.1.0",
    "Microsoft.Extensions.Logging.Console": "1.1.0",
    "Microsoft.Extensions.Logging.Debug": "1.1.0",
    "Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0",
    "Microsoft.AspNetCore.ResponseCompression": "1.0.0"
  },
  ...

Step 2: Update and configure services in the project Startup.cs file

We now just need to add a couple of lines to the Startup.cs project file, which will:

  • Add the services available to the runtime container, and
  • Use the services in the HTTP pipeline at runtime.

I’ve highlighted the lines that I added in bold red font in the code below.

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
        Configuration = builder.Build();
    }
 
    public IConfigurationRoot Configuration { get; }
 
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddResponseCompression();
 
        // Add framework services.
        services.AddMvc();
    }
 
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseResponseCompression();
 
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();
 
        app.UseMvc();
    }
}

Now when I call my web service, all responses are zipped by default.

We can prove this by looking at the headers sent with the response – I’ve pasted a screenshot of the headers sent back when I call a GET method in my Web API service. There is a header named “Content-Encoding” which has the value “gzip” – this signals that the response has been zipped.

screenshot-1480371947

Wrapping up

This is a really easy way to improve the performance of your website or your web service – this is one of the first things I configure when starting a new project.

Continue reading

.net, Performance

How to set a maximum time to allow a C# function to run for

Sometimes we’d like to set a maximum time allowed for a method. One example is when our code is communicating with an external dependency which stops responding e.g. a database connection, or a piece of of hardware which freezes up.

Let’s invent a scenario to examine this further.

Say I have a long running method – this randomly takes between one and ten seconds to return an integer.

private static int LongRunningMethod()
{
    var r = new Random();
 
    var randomNumber = r.Next(110);
 
    var delayInMilliseconds = randomNumber * 1000;
 
    Task.Delay(delayInMilliseconds).Wait();
    
    return randomNumber;
}

But also say I don’t want to wait longer than a maximum of three seconds. How can I throw a TimeoutException after waiting for three seconds?

Task.Run to the rescue

In .NET, a Task is something that you want to do. It’s possible to pass a function to the Run method of Task, which will run that function asynchronously in a separate thread, and return a Task object.

So what? Well, since a Task object is immediately returned by the Task.Run method, we can call the Task’s Wait method, and wait for three seconds for the task to complete. If it has successfully completed, this method returns true. If it hasn’t completed, it returns false. So we can test the output, and return an output depending on what we want to do.

var task = Task.Run(() =>
{
    return LongRunningMethod();
});
 
bool isCompletedSuccessfully = task.Wait(TimeSpan.FromMilliseconds(3000));
 
if (isCompletedSuccessfully)
{
    return task.Result;
}
else
{
    throw new TimeoutException("The function has taken longer than the maximum time allowed.");
}

This pattern can be used to improve the performance of my code – it ensures that if my application locks up for whatever reason, I know I can control the maximum length of time that it’ll lock up for.

.net, C# tip, Performance

Using the BackgroundWorker object in C# to improve application responsiveness

Most of the software that I build is for the web – because of that, I’ve not had to deal with using threads too much. In fact, there was only one time that I have worked on a web project where threads were used – a (seriously smart) developer built something using threads that was a pre-cursor to the .NET Async/Await model. It worked great when it worked, but it wasn’t our favourite bit of the codebase to make changes to.

puppy_multithreading

Recently I’ve been doing some Windows Forms development, and I’ve come up against the old problem of the GUI freezing when I performed an processor intensive operation. I wanted to find a way of carrying out this intensive operation on a different thread to the GUI, but ideally I wanted a way to avoid the traditional code complexity when trying to manage and release different threads.

The BackgroundWorker object

A colleague recommended that I look into the BackgroundWorker object – this object allows an intensive operation to work on a different thread to the GUI, and I can interact with this through an event model.

I’ll try to cut this down to the absolute bare bones before looking at an example. There are two events that I really care about – DoWork and RunWorkerCompleted.

  • I put the intensive operation into the DoWork event handler.
  • If anything needs to be done when the intensive operation completes (e.g. a notification), this goes into RunWorkerCompleted.

Finally, I can start the BackgroundWorker thread by calling the RunWorkerAsync() method.

How to use a BackgroundWorker

The code below isn’t meant to represent best practice – it’s a bare bones explanation of how to use the BackgroundWorker’s most important events.

I used Visual Studio to create a sample Windows Form application – inside the form’s code behind class, the form’s constructor is extremely simple:

public SampleForm() {
    InitializeComponent();  
}

Now I can add the code for the background worker – I’ve pasted the code for the class below.

public partial class SampleForm : Form
{
    private BackgroundWorker worker = new BackgroundWorker();

    public SampleForm()
    {
        InitializeComponent();

        // register background worker events
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;

        // start background worker in different thread to the GUI
        worker.RunWorkerAsync();
    }

    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        // This is where the processor intensive code should go
        ProcessorIntensiveCode();

        // if we need any output to be used, put it in the DoWorkEventArgs object
        e.Result = "all done";
    }

    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // will output "all done" to the console
        Console.WriteLine((string)e.Result);
    }
}

And that’s about it – no need for complex thread management code. There’s quite a bit more that can be done with this object – you can report on progress for example, and report back to the GUI thread how far you’ve got through the intensive operation. But hopefully this explains the core features of this really useful class.