Course contentsShow
← C#
Lesson 1748 of 1,90816. Performance and DiagnosticsFree lesson

Working with Span and Memory for Zero-Copy Operations

Students will implement high-performance parsing techniques using windowed memory views.

In this lesson, you will learn how to use Span<T> and Memory<T> to perform high-performance parsing by creating windowed views into existing memory without allocating new objects.

The Problem: Traditional Slicing

In standard C#, if you need to extract a part of a string or an array—like parsing a specific field from a incoming network buffer—you typically use string.Substring() or LINQ’s Skip().Take(). These methods create new objects on the heap. In a high-throughput system, these "temporary" allocations trigger frequent Garbage Collection (GC) cycles, slowing down your application.

The Solution: Zero-Copy Views

Span<T> and Memory<T> allow you to create a "view" or a "window" into an existing buffer. Because they are designed to be stack-only (in the case of Span<T>) or reference-counted (for Memory<T>), they don't copy the underlying data. You are simply pointing to a segment of memory that already exists.

Implementing a Windowed Parser

Consider a raw data buffer received from a socket. Instead of copying bytes to extract a message, you create a slice:

public void ProcessBuffer(byte[] buffer)
{
    // Create a Span view over the entire array
    Span<byte> data = buffer;

    // Create a "window" into the first 10 bytes without allocation
    Span<byte> header = data.Slice(0, 10);

    // Perform operations on the window
    if (header[0] == 0x01)
    {
        // ... logic
    }
}

By using Slice(), the runtime does not copy the data from the original buffer into header. It simply adjusts the internal pointer and length property of the Span. This is the essence of zero-copy: you are parsing the data in place.

Important Constraints

Because Span<T> is a ref struct, it can only live on the stack. This ensures that a Span cannot outlive the memory it is pointing to, preventing memory safety issues. If you need to pass a view to an asynchronous method (where the stack might disappear), use Memory<T> instead, which can reside on the heap and track the lifetime of the underlying buffer safely.

Key Takeaway: Use Span<T> for high-performance, stack-bound slicing to perform logic on memory buffers without triggering heap allocations or copying data.