๐—ฆ๐—ฝ๐—ฎ๐—ป ๐˜ƒ๐˜€ ๐— ๐—ฒ๐—บ๐—ผ๐—ฟ๐˜† ๐—ถ๐—ป .๐—ก๐—˜๐—ง: ๐—จ๐—ป๐—ฑ๐—ฒ๐—ฟ๐˜€๐˜๐—ฎ๐—ป๐—ฑ๐—ถ๐—ป๐—ด ๐—›๐—ถ๐—ด๐—ต-๐—ฃ๐—ฒ๐—ฟ๐—ณ๐—ผ๐—ฟ๐—บ๐—ฎ๐—ป๐—ฐ๐—ฒ ๐— ๐—ฒ๐—บ๐—ผ๐—ฟ๐˜† ๐— ๐—ฎ๐—ป๐—ฎ๐—ด๐—ฒ๐—บ๐—ฒ๐—ป๐˜

When building high-performance .NET applications, reducing memory allocations can significantly improve performance and lower garbage collection (GC) pressure.

That’s where Span<T> and Memory<T> come in.

Although they look similar, they are designed for different scenarios. Understanding when to use each can help you write faster and more memory-efficient applications.

What is Span<T>?

Span<T> is a lightweight type that provides a safe and efficient view over a contiguous region of memory.

Instead of creating a copy of an array or string, it lets you work with the existing memory directly.

Example:

int[] numbers = { 10, 20, 30, 40, 50 };

Span<int> firstThree = numbers.AsSpan(0, 3);

foreach (var number in firstThree)
{
    Console.WriteLine(number);
}

No new array is created.

The span simply references the existing memory.


Why is Span<T> Fast?

Normally, slicing an array creates another array.

var copy = numbers[0..3];

This allocates additional memory.

Using Span<T>:

Span<int> slice = numbers.AsSpan(0, 3);

No allocation.

No copying.

Less GC pressure.


Important Limitation of Span<T>

Span<T> is a stack-only type (ref struct).

Because of this:

  • It cannot be stored in a class field.
  • It cannot be boxed.
  • It cannot implement interfaces.
  • It cannot be used across await or yield boundaries.

These restrictions exist to ensure memory safety.


What is Memory<T>?

Memory<T> represents the same concept as Span<T>, but it can safely live on the managed heap.

This means it works well in asynchronous and long-lived scenarios.

Example:

Memory<byte> buffer = new byte[4096];

await ProcessAsync(buffer);

Inside the async method:

public async Task ProcessAsync(Memory<byte> memory)
{
    await Task.Delay(100);

    Span<byte> span = memory.Span;

    // Process data
}

Memory<T> survives across await, while Span<T> cannot.


Span vs Memory

FeatureSpanMemory
Stack-onlyโœ…โŒ
Heap allocationโŒโœ…
Works with asyncโŒโœ…
Can be stored in fieldsโŒโœ…
Best forSynchronous operationsAsynchronous operations

When Should You Use Each?

Use Span<T> when:

  • Processing arrays
  • Parsing strings
  • Working synchronously
  • Optimizing performance-critical code

Use Memory<T> when:

  • Working with async methods
  • Long-lived buffers
  • Pipelines
  • Network programming
  • File I/O

Real-World Examples

Span<T> is commonly used in:

  • String parsing
  • Serialization
  • JSON processing
  • High-performance algorithms

Memory<T> is commonly used in:

  • ASP.NET Core
  • System.IO.Pipelines
  • Networking
  • Streaming large files

Final Thoughts

Span<T> and Memory<T> are powerful additions to modern .NET that help developers write faster, allocation-efficient code.

The rule is simple:

  • Need fast, synchronous access? Use Span<T>.
  • Need async or long-lived memory? Use Memory<T>.

Choosing the right type can reduce allocations, improve performance, and make your applications more scalable.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *