Skip to content

API Proposal: Add Span accessor for MemoryMapped files #37227

@Suchiman

Description

@Suchiman

Background and Motivation

.NET had acccess to memory mapped files for a long time but using them either requires unsafe pointers, a BinaryReader|Writer like API or Stream. With the advent of Span one could access them more easily and pass them directly without intermediate copies / buffers to a larger set of APIs.

Proposed API

We would add

namespace System.IO
{
    public class MemoryMappedFile : IDisposable
    {
+        public MemoryMappedMemoryManager CreateMemoryManager();
+        public MemoryMappedMemoryManager CreateMemoryManager(long offset, int size);
+        public MemoryMappedMemoryManager CreateMemoryManager(long offset, int size, MemoryMappedFileAccess access);
    }

+    public class MemoryMappedMemoryManager : MemoryManager<byte>
+    {
+    }
}

Unlike most other Span APIs we allow passing long offset and int size in order to work with files larger than 2GB which we cannot directly slice into due to all Span related classes being int length based. If you need to work with files larger than 2GB, you need to call CreateMemoryManager with increasing offsets.

Usage Examples

using MemoryMappedFile file = MemoryMappedFile.CreateFromFile("test.txt");
using MemoryMappedMemoryManager manager = file.CreateMemoryManager();
Memory<byte> memory = manager.Memory;
Console.WriteLine(Encoding.UTF8.GetString(memory.Span));

Alternative Designs

We could also add a string.Create like API to the MemoryMappedViewAccessor where MemoryMappedViewAccessor manages the lifecycle and the design ensures that the Span does not outlive the MemoryMappedViewAccessor.

namespace System.IO
{
    public class MemoryMappedViewAccessor : IDisposable
    {
+        public void UseSpan<TState>(TState state, SpanAction<byte, TState> action);
+        public TResult UseSpan<TState, TResult>(TState state, SpanAction<byte, TState> action);
    }

which would be used like

using MemoryMappedFile file = MemoryMappedFile.CreateFromFile("test.txt");
using MemoryMappedViewAccessor accessor = file.CreateViewAccessor();
accessor.UseSpan((object)null, (span, state) =>
{
    Console.WriteLine(Encoding.UTF8.GetString(span));
});

Risks

Low risk as far as only adding APIs is concerned.
Designs that allow the Span to outlive the memory mapped file could encounter an access violation if trying to use the span past that point.

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-suggestionEarly API idea and discussion, it is NOT ready for implementationarea-System.IO

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions