Start Debugging

Building a Microsecond-Latency Database Engine in C#

Loic Baumann's Typhon project targets 1-2 microsecond ACID commits using ref structs, hardware intrinsics, and pinned memory, proving C# can compete at the systems programming level.

The assumption that high-performance database engines require C, C++, or Rust is deeply ingrained. Loic Baumann’s Typhon project challenges that directly: an embedded ACID database engine written in C#, targeting 1-2 microsecond transaction commits. The project recently hit the front page of Hacker News, sparking a lively debate about what modern .NET can actually do.

The Performance Toolkit in Modern C#

Baumann’s core argument is that the bottleneck in database engine design is memory layout, not language choice. Modern C# provides the tools to control memory at a level that would have been impossible a decade ago.

ref struct types live exclusively on the stack, eliminating heap allocations on hot paths:

ref struct TransactionContext
{
    public Span<byte> WriteBuffer;
    public int PageIndex;
    public bool IsDirty;
}

For memory regions that must never move, GCHandle.Alloc with GCHandleType.Pinned keeps the garbage collector out of critical sections. Combined with [StructLayout(LayoutKind.Explicit)], you get C-level control over every byte offset:

[StructLayout(LayoutKind.Explicit, Size = 64)]
struct PageHeader
{
    [FieldOffset(0)]  public long PageId;
    [FieldOffset(8)]  public long TransactionId;
    [FieldOffset(16)] public int RecordCount;
    [FieldOffset(20)] public PageFlags Flags;
}

Hardware Intrinsics for Hot Paths

The System.Runtime.Intrinsics namespace gives direct access to SIMD instructions. For a database engine scanning pages or computing checksums, this is the difference between “fast enough” and “competitive with C”:

using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;

static unsafe uint Crc32Page(byte* data, int length)
{
    uint crc = 0;
    int i = 0;
    for (; i + 8 <= length; i += 8)
        crc = Sse42.Crc32(crc, *(ulong*)(data + i));
    for (; i < length; i++)
        crc = Sse42.Crc32(crc, data[i]);
    return crc;
}

Enforcing Discipline at Compile Time

One of the more interesting aspects of Typhon’s approach is using Roslyn analyzers as safety rails. Custom analyzers enforce domain-specific rules (no accidental heap allocations in transaction code, no unchecked pointer arithmetic outside approved modules) at compile time rather than relying on code review.

Constrained generics with where T : unmanaged provide another layer, ensuring that generic data structures work only with blittable types that have predictable memory layouts.

What This Means for .NET

Typhon is not a production database yet. But the project demonstrates that the gap between C# and traditional systems languages has narrowed significantly. Between Span<T>, hardware intrinsics, ref struct, and explicit memory layout control, .NET 10 gives you the building blocks for performance-critical systems work without leaving the managed ecosystem.

The full write-up is worth reading for the architectural details and benchmarks.

< Back