11

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.

Useme Alehosaini
  • 2,760
  • 6
  • 17
  • 25
Red Riding Hood
  • 1,570
  • 12
  • 31
  • 3
    Are you sure having these arrays fully occupying memory is sensible in the first place? Might a `MemoryMappedFile` be a better starting point? Without knowing your use cases it's going to be difficult for anyone to offer concrete advice. – Damien_The_Unbeliever Sep 07 '18 at 14:43
  • ArraySegment is just a convenience tool to avoid having to add the offset of the segment each time you access the element. Under the hood it still does it, which adds some cost to each call. Memory objects are as efficient as C# arrays. – Thinko Sep 07 '18 at 14:46
  • The use case is stitching images together. The resulting image needs to be encoded to .png, hence requiring the whole file to be in memory. – Red Riding Hood Sep 07 '18 at 14:46
  • 2
    Does this answer your question? [How is the new C# Span different from ArraySegment?](https://stackoverflow.com/questions/49020894/how-is-the-new-c-sharp-spant-different-from-arraysegmentt) – CoolBots Aug 21 '20 at 03:13
  • 1
    `ArraySegment` is older, hence why it exists. I'd use `Memory` (or `Span`, as needed) in all new code. – Etienne de Martel Nov 18 '20 at 16:02

1 Answers1

1

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);
MikeJ
  • 1,154
  • 6
  • 9
  • I would add that the standard API seems to be moving toward favoring `Memory` and `Span` over arrays. For example, [`SocketAsyncEventArgs.MemoryBuffer`](https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.socketasynceventargs.memorybuffer). – StackOverthrow Nov 18 '20 at 16:05