GC Allocate Array

In this post I will examine the GC Allocate Array methods along with other array creation alternatives.

Previously, I have looked into array allocation with when investigating SkipInitLocal. In that post it turned out the larger the array was, the larger the gain was to use stack allocation with [SkipInitLocal] attribute.

However during exercise I noticed that the current implementation of ArrayPool has been using GC.AllocateUninitializedArray<T> to create the arrays for its internal pool.

Creating Arrays

Find out more


What is New here? - aka 4 ways or creating structs

In this post I will investigate 4 different approaches for creating structs and I will measure their performance characteristics.

The release of C# 10 removed a previous restriction on struct constructors: structs are allowed have default constructors. This means the code below compiles without a build error.

public struct Person
{
    public int Age { get; set; } = 1;

    public string Name { get; set; } = "Foo";
}

In this case the default constructor will set the property values as 1 and Foo respectively. This behavior is really similar to classes. The 4 ways this post explores creating structs:

Find out more


SkipInitLocal or ArrayPool

Many data processing algorithms require a temporary data storage for certain operations. I have been recently working with one such algorithm in the sound processing domain. In my case a fixed sized temporary byte array has been required for a method execution. In a performance sensitive code, one would prefer to achieve a non-allocating solution for this problem.

In the particular case it was a tight loop for processing live sound data. Allocating a new array for every iteration of the loop is excessive. However, I could also not use a pre-allocated array for the purpose, due to the structure of the code. There are still a few options to acquire a temporary array:

ArrayPool type provides a shared pool of arrays, from which a developer might rent an array, and return it once it is no longer needed. This array exists on the heap as a regular array, and the ArrayPool makes sure to provide an array when renting which is at least the size asked for. Because the array is returned to the pool after usage, the next iteration of the algorithm may re-use the same array, avoiding any excess allocation.

Find out more


The wrong answer for a performance question

At a recent event I have challenged a design and implementation from performance point of view. My concern was using the C# decimal type over double when there was no need for it from number- precision, calculation, or representation side. I was curious if the developers have made their "due diligence" and compared the performance impact of choosing one type over another.

To summarize the answer to my questions in short, no measurements were made by the developers. However, to address my curiosity, I was told that the operation in question "only takes a few seconds" and it was also demonstrated by clicking a button that triggers the operation and a few seconds later the results were displayed. All good, business stakeholders were happy, and the event continued. It was not a forum to get into a deeper discussion about this answer. I have seen similar responses in the past, but unfortunately, I cannot think of a single aspect of the response that would be answering the question.

First, a single click and a demonstration of the operation is not a performance measurement. No numbers were involved, no resource utilization was measured, no throughput and latency has been calculated. Moreover, you cannot even reason about these numbers from a single request. Second, the business has not set any performance goals. Third, the demonstration happened on a test environment with minimal test data and a single user putting load on the system. Finally, I asked for a performance comparison between two implementations, but the answer and the demonstration did not touch this aspect.

Because I do not have the environment and the code to run and measure such operation, I will have to rely on generic reasoning and assumptions to explain why I was eager to see such performance comparison.

Find out more


Faster Bound Checks

In a recent pull request I received some comments on how to do bound checks better when indexing into arrays. The original code received a span and an index (scan). If the index was larger to the span's length, it returned minus one. Otherwise it indexes into the buffer and does a further lookup.

private static int ReadHex(int scan, ReadOnlySpan<char> buffer)
{
    if (scan >= buffer.Length)
        return -1;
    int c = buffer[scan];
    return c >= CharToHexLookup.Length ? -1 : CharToHexLookup[c];
}

After implementing the suggestion, the code looks nearly identical, but it is using uint types for the comparing the index variable with the length of the bugger:

private static int ReadHex(int scan, ReadOnlySpan<char> buffer)
{
    if ((uint)scan >= (uint)buffer.Length)
        return -1;
    int c = buffer[scan];
    return c >= CharToHexLookup.Length ? -1 : CharToHexLookup[c];
}

Find out more