Laszlo

Hello, I am Laszlo

Software-Enginner, .NET developer

Contact Me

AsAsyncEnumerable Extension

This post explores a template implementation of method that converts an IEnumerable<T> to IAsyncEnumerable<T>. IAsyncEnumerable has been introduced to provide asynchronous iteration over values. The following implementation takes a synchronous enumerable and converts it to asynchronous, allowing the execution of async code in-between each iteration of the source. One could achieve similar results by using a regular foreach loop with an await-ed method in the loop body. However, one might want to create an extension method over for simplified syntax as shown below.

This sample extension method and type contains no 'real' async method invocation, but a developer can easily extend it with a tailored async method call or a delegate (Func<T,Task>) invocation. A good place for such a call would be in the body of MoveNextAsync method. This type as-is only useful for converting sync enumerable to async for example, for mocking purposes in unit tests.

Design decisions for the following type follow the design of the built-in Iterator of .NET class library.

  • The source argument is validated without the need of iterating the AsyncEnumerable<T> instance.

  • The iterator does not cancel iteration itself, based on co-operative cancellation it could (should) pass the cancellation token async method invoked.

  • The enumerable and the enumerator are implemented by the same type.

  • The state of the enumerator is captured by the _state variable.

  • The iterator is not thread-safe.

  • The inner iterator is initialized lazily.

  • The Current property returns default in non-iterating states, which may be null.

Find out more »


DependentHandle Impacts Performance

DependentHandle is a special type of handle provided by the .NET Garbage Collector (GC).

This handle creates a dependency between the lifetime of two objects. It has a 'weak' reference to a target object and a reference to a dependent object. The weak reference to the target object means that a dependent handle does not extend the lifetime of this target object. The reference to the dependent object remains live as long as the target object is live.

Use-Case

A common use case for DependentHandle is when you need to associate additional fields with an object without extending its lifetime through a strong reference. While this type is not commonly used in typical line-of-business (LOB) applications, it is a handy tool for debuggers, profilers, and other diagnostic or development-time features. A special ConditionalWeakTable also exists, allowing a collection of DependentHandles to be stored in memory.

Find out more »


Params ReadOnlySpan

I have recently come across a method in C# that is best resembled by the following method:

public int Sum(IEnumerable<int> values)
{
    int sum = 0;
    foreach (var value in values)
        sum += value;
    return sum;
}

The actual method body looks different, the signature of the method is identical. This method is invoked at 30-40 callsites, and the majority of callsites look like:

Sum([1]);
// or
Sum([1, 2]);
// or
Sum([1, 2, 3]);

Find out more »


Division in Assembly

HTTP/3 specification reserves a range of identifiers for streams and frame types. The range as 0x1f * N + 0x21 for non-negative integer values of N.

A received identifier should be validated against the reserved range. This involves subtrackting 33 and then validating if the result is a multiple of 31. The number 31 holds special importance in this context as it is represented by 2N - 1, or 0x0001_1111. This property influences the approaches used for validation.

Several strategies were considered to verify whether a value is a multiple of 31:

  • bit manipulation (summing every 5 bits) value to check if the sum is a multiple of 31.

  • lookup table

  • using divrem Input % 31 == 0

  • using integer division and multiplication (Input / 31) * 31 == Input

  • multiplication and bit shifting (divide by 2).

Find out more »


Task over ValueTask<>

I recently ran into some code that extensively used ValueTask types along with Task. I became curious if it is a good idea to mix async ValueTask<>s and Tasks. Moreover, .NET allows decorating methods returning ValueTask<> types with [AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))] that adds pooling behavior, which reduces allocations.

There are many ways to invoke async methods from another async method. The invoked async method can return a Task, ValueTask<>, or a pooled ValueTask<>; the calling method can also return any of these response types, and be a sync or async method. In this post, I create combinations of these methods to measure their performance footprint. The inner method may complete synchronously, asynchronously, or with a probability set between 0..1, where 1 means synchronous completion.

In this blog post, 'sync' completion refers to returning the result of an underlying async method without awaiting it, or without .Result / .GetAwaiter().GetResult() calls. It does not refer to the 'sync-over-async' anti-pattern.

I used BenchmarkDotNet to measure the performance and allocations of these method combinations. Please note that the allocations show 'non-round' numbers due to BenchmarkDotNet's aggregation when the probability falls between 0 and 1 exclusively. Async completions invoke Task.Yield(); - which yields execution of the current task, allowing other tasks to execute. While there should be no other tasks running in the benchmark, the Mean performance results include a non-trivial waiting duration, that is for the task continuation to execute.

Find out more »