MemoryMappedViewAccessor性能解决方法

时间:2018-03-17 17:28:20

标签: c# dispose memory-mapped-files unsafe

避免XY问题的背景:

我有一个程序通过MemoryMappedFile.CreateFromFileCreateViewAccessor使用只读内存映射文件来读取二进制数据。阅读假设通过ReadUInt32上的ReadUInt16ReadByteReadArrayMemoryMappedViewAccessor工作,但事实证明这是非常慢。据我所知,Read*函数为每次读取分别获取指向内存的底层指针。 获取指针也涉及同步,因此使用多个线程/任务来访问文件实际上会减慢访问速度。

我已经重写了类以通过构造函数中的SafeMemoryMappedViewHandle.AcquirePointer获取指向内存的指针,并尝试通过IDisposable接口实现正确的清理。不幸的是,大于Read*的类型的byte函数可能需要未对齐的访问。在x86上,*(UInt32*)(pointer)可以正常工作,但这显然不是便携式或安全的。

1)以下IDisposable接口的使用是否正确?

2)如何从内存映射文件中正确且可移植地进行未对齐读取?

或3)有没有办法减少明确只读映射的MemoryMappedViewAccessor.Read*函数的开销?

public unsafe class MyReader : IDisposable
    {
        private readonly MemoryMappedFile mmf;
        private readonly MemoryMappedViewAccessor mma;
        private readonly byte* pointer;
        private bool disposed = false;

        public MyReader (string filename)
        {
            mmf = MemoryMappedFile.CreateFromFile (filename, FileMode.Open, filename, 0, MemoryMappedFileAccess.Read);
            mma = mmf.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read);
            mma.SafeMemoryMappedViewHandle.AcquirePointer (ref pointer);
        }

        private UInt32 ExampleReadAccess (long pos)
        {
            //return mma.ReadUInt32 (pos); //Way too slow, at least 2x slower than the following
            return *(UInt32*)(pointer + pos);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposed) return;
            mma.SafeMemoryMappedViewHandle.ReleasePointer();
            if (disposing)
            {
                mma.Dispose();
                mmf.Dispose();
            }
            disposed = true;
        }

        ~MyReader()
        {
            Dispose(false);
        }
}

0 个答案:

没有答案