Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use ArraySegment<T> over Memory<T>?

Tags:

c#

I was researching the best way to return 'views' into a very large array and found ArraySegment which perfectly suited my needs. However, I then found Memory<T> which seems to behave the same, with the exception of requiring a span to view the memory.

For the use-case of creating and writing to views into a massive (2GB+) array, does it matter which one is used?

The reasons for the large arrays are they hold bytes of an image.

like image 562
Red Riding Hood Avatar asked Sep 07 '18 14:09

Red Riding Hood


People also ask

Why use span T?

Span<T> is a new value type at the heart of . NET. It enables the representation of contiguous regions of arbitrary memory, regardless of whether that memory is associated with a managed object, is provided by native code via interop, or is on the stack.

What is an ArraySegment?

Remarks. ArraySegment<T> is a wrapper around an array that delimits a range of elements in that array. Multiple ArraySegment<T> instances can refer to the same original array and can overlap.

What is a ArraySegment in C#?

C# ArraySegment structure can be used to get a segment of an array. The ArraySegment takes a range of items. The structure has two forms of constructors. ArraySegment<T>(T[]) : Creates ArraySegment instance from an entire array.

What is a ReadOnlySpan?

A ReadOnlySpan<T> instance is often used to reference the elements of an array or a portion of an array. Unlike an array, however, a ReadOnlySpan<T> instance can point to managed memory, native memory, or memory managed on the stack.


1 Answers

Memory is sort of a wrapper around Span - one that doesn't have to be on the stack. And as the link provided by CoolBots pointed out it's an addition to arrays and array segments not really a replacement for them.

The main reason you would want to consider using Span/Memory is for performance and flexibility. Span gives you access to the memory directly instead of copying it back and forth to the array, and it allows you to treat the memory in a flexible way. Below I'll go from using the array as bytes to using it as an array of uint.

I'll skip right to Span but you could use AsMemory instead so you could pass that around easier. But it'd still boil down to getting the Span from the Memory.

Here's an example:

        const int dataSize = 512;
        const int segSize = 256;

        byte[] rawdata = new byte[dataSize];

        var segment = new ArraySegment<byte>(rawdata, segSize, segSize);

        var seg1 = segment.AsSpan();

        var seg1Uint = MemoryMarshal.Cast<byte, uint>(seg1);

        for (int i = 0; i < segSize / sizeof(uint); ++i)
        {
            ref var data = ref seg1Uint[i];

            data = 0x000066;
        }

        foreach (var b in rawdata)
            Console.WriteLine(b);
like image 64
MikeJ Avatar answered Sep 21 '22 20:09

MikeJ