Method Size and CPU

Usually, assembly code size is good measure to have for performance optimizations. In this post I plan to gain an understanding why smaller assembly code size might be beneficial and how this affects the performance.

Problem

To answer this question, I prepare two methods to compare. How can I create two methods that do the same operations in essence but differ in code size that is executed?

Instead of writing 2 methods to compare, I decided to write ~2000 methods:

Find out more


The Best Way to ArgumentValidation

Introduction to Argument Validation

In .NET7 we can do 3 different style of argument validation against null arguments. In this post I will check which one is the most performant.

The first example is the poor man's validation. We check if the input parameter is null, and if so an ArgumentNullException object is instantiated and thrown. This style of argument validation has been around for an awfully long time in .NET.

public int CustomArgumentValidationImpl(Data? input)
{
    if (input == null)
        throw new ArgumentNullException(nameof(input));
    return input.Value;
}

Find out more


Understanding RuntimeHelpers.IsKnownConstant Method

In this post my goal is to gain understanding of the RuntimeHelpers.IsKnownConstant method. I have come across it in the Performance Improvements in .NET 7 blog post. There are two examples presented in the post:

  • bool StartsWith(char value)

  • Math.Round with MidpointRounding mode is specified

I will learn about JIT optimization including RuntimeHelpers.IsKnownConstant through a simple and slightly artificial example. A bool IsPalindromePosition(int position) method is part of a type which has a static property ReadOnlySpan<char> Text. The method returns true when the given position from the beginning of the string returns the same character as one from the end. For the sake of simplicity this method omits all input validation.

public static ReadOnlySpan<char> Text => "hellobolleh";

[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public bool IsPalindromePosition(int position)
{
    if (int.IsOddInteger(Text.Length) && position == Text.Length / 2 + 1)
        return true;

    return Text[position] == Text[Text.Length - position - 1];
}

[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
public bool Work()
{
    var result = IsPalindromePosition(0);
    return result;
}

Find out more


Kestrel Serving Requests

In this post I review the way Kestrel serves HTTP requests. Please note, that the architecture described here may change from release to release of ASP.NET Core. At the time of writing .NET 7 and the corresponding ASP.NET Core is a month away from release.

Accepting connection on HTTP2 and HTTP3

ASP.NET Core's Kestrel opens IConnectionListener<T>s upon startup. For each ASPNETCORE_URLS set, a connection listener is instantiated. A base IConnectionListener implementation is a SocketConnectionListener. Connection listeners implement the decorator pattern. For example, GenericConnectionListener expects another connection listener as a constructor parameter.Connection listeners provide basic functionality to bind/unbind to a given port and to accept new connection requests.

ConnectionDispatcher also initiated during startup. It starts to run an infinite while loop in AcceptConnectionsAsync() method to accept new connections on a given listener. When a client sends a request, a new connection in initialized. In this case a KestrelConnection<T>, that also implements IThreadPoolWorkItem.Execute().

Find out more


Streams, Pipes and gRPC

.NET 7 introduces new methods for Stream type: ReadExactly(...), ReadAtLeast(...) and their async counterparts allow the developers to await 'enough' data to be present for further processing input streams.

At the time of writing this post .NET 7 is still in preview bits. Which means there is still a chance that these methods will not be released.

Why do we have it?

At first these methods may seem a surplus, as developers have been using streams for many years, so why would we need them? There are several workloads in software stack that fits perfectly with this concept. Or rather say payloads instead of workloads.

Find out more