title: MemoryMappedViewAccessor performance workaround
body: <p>Context for avoiding XY-Problem:</p>
  
  <p>I have a program that uses read-only memory mapped files via <code>MemoryMappedFile.CreateFromFile</code> and <code>CreateViewAccessor</code> to read binary data. Reading was <em>supposed</em> to work via <code>ReadUInt32</code>, <code>ReadUInt16</code>, <code>ReadByte</code> and <code>ReadArray</code> on the <code>MemoryMappedViewAccessor</code>, but this turns out to be extremely slow. As best as I can tell, the <code>Read*</code> functions acquire the underlying pointer to the memory separately for every read.
  Acquiring the pointer also involves synchronization, so using multiple threads/tasks to access the file actually slows the accesses down.</p>
  
  <p>I have rewritten the class to acquire the pointer to the memory via <code>SafeMemoryMappedViewHandle.AcquirePointer</code> in the constructor, and attempted to implement correct cleanup via the <code>IDisposable</code> interface. Unfortunately, the <code>Read*</code> functions for types greater than <code>byte</code> may require unaligned accesses. On x86, <code>*(UInt32*)(pointer)</code> works, but this is obviously not portable or safe.</p>
  
  <p>1) Is the following use of the <code>IDisposable</code> interface correct?</p>
  
  <p>2) How can I correctly and portably do unaligned reads from the memory mapped file?</p>
  
  <p>or 3) Is there a way to reduce the overhead of the <code>MemoryMappedViewAccessor.Read*</code> functions for explicitly read-only mappings?</p>
  
  <pre><code>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);
          }
  }
  </code></pre>