如何从.NET中的内存映射文件中快速读取字节?

Kie*_*one 21 .net c# memory-mapped-files

在某些情况下,MemoryMappedViewAccessor类只是没有削减它以有效地读取字节; 我们得到的最好的是通用ReadArray<byte>,它是所有结构的路由,当你需要字节时涉及几个不必要的步骤.

可以使用a MemoryMappedViewStream,但因为它基于Stream你需要首先寻找正确的位置,然后读操作本身有许多不必要的步骤.

是否有快速,高性能的方法从.NET中的内存映射文件读取字节数组,因为它应该只是地址空间的特定区域来读取?

Kie*_*one 32

这个解决方案需要不安全的代码(用/unsafeswitch 编译),但直接抓取指向内存的指针; 然后Marshal.Copy可以使用.这比.NET框架提供的方法快得多.

    // assumes part of a class where _view is a MemoryMappedViewAccessor object

    public unsafe byte[] ReadBytes(int offset, int num)
    {
        byte[] arr = new byte[num];
        byte *ptr = (byte*)0;
        this._view.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr);
        Marshal.Copy(IntPtr.Add(new IntPtr(ptr), offset), arr, 0, num);
        this._view.SafeMemoryMappedViewHandle.ReleasePointer();
        return arr;
    }

    public unsafe void WriteBytes(int offset, byte[] data)
    {
        byte* ptr = (byte*)0;
        this._view.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr);
        Marshal.Copy(data, 0, IntPtr.Add(new IntPtr(ptr), offset), data.Length);
        this._view.SafeMemoryMappedViewHandle.ReleasePointer();
    }
Run Code Online (Sandbox Code Playgroud)

  • 您应该使用关键执行块和try-finally来确保即使Marshal.Copy抛出异常也会运行ReleasePointer. (6认同)
  • 好的答案=)确实,分析显示托管包装器比使用不安全指针访问映射内存慢30倍. (3认同)
  • @MattHowells我同意.我读到CER可能会影响性能,但似乎可以忽略不计(至少在受控测试中).无论性能如何,它都是正确的使用模式,如"备注"中所述; https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safebuffer.acquirepointer(v=vs.110).aspx (2认同)