Unnecessary reads in memory mapped files when writing only

41 Views Asked by At

I'm having a simple application that is just writing into a memory mapped file, without ever reading from it. So what I'm doing is to have a simple loop that writes 50 blocks of an array of the size 4096*100 into the memory mapped file or better into the memory represented by the memory mapped file. Since I'm only writing to it I thought there will never by a read IRP request, but obviously 20 read IRP issues (which in total corresponds to the memory I'm writing and is a multiple of the sector size), whereas there is only one write. The interesting thing is that the write is even performend since there is enough memory and the file was marked with DeleteOnClose, so there would be no need to write it when the result is discarded. But this might be a problem of the implementation of the memory mapped files in .NET (see here: https://github.com/dotnet/runtime/issues/59606)

Im bothered by the fact that unncessary reads are performed. The problem is that there is mostly now real knowledge about memory mapped files since most of my answer stay unanswered. So maybe someone can guide me to some sources where I can find more information abiut memory mapped files.

[Update 1] I'm currently doing my own file-mapping, without using memory mapped files, here I'm simply allocating memory, if the file was allocated fresh. So I know that the memory has never been written before. I would expect something similar from the MMF-Files.

using System;
using System.IO;
using System.IO.MemoryMappedFiles;

namespace MemoryMappedFileTest
{
    class Program
    {
        // Size of a single block in bytes
        const int SizeOfBlock = 4096 * 100;

        // Number of blocks.
        const int NoOfBlocks = 50;

        // Name of the test file.
        const string FileName = "E:\\MMF\\mm.dat";

        static unsafe void Main(string[] args)
        {
            // Create the temporary which is deleted on close.
            using var stream = new FileStream(FileName, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.ReadWrite, 4096, FileOptions.DeleteOnClose);

            // Create the file mapping and the view
            using var mm = MemoryMappedFile.CreateFromFile(stream, null, NoOfBlocks * (long)SizeOfBlock, MemoryMappedFileAccess.ReadWrite, HandleInheritability.None, false);
            using var va = mm.CreateViewAccessor();

            // Get the absolute start address
            var StartAddress = va.SafeMemoryMappedViewHandle.DangerousGetHandle();

            // Create some empty block data we can write.
            var BlockData = new byte[SizeOfBlock];

            // Run through the blocks and write 0s in it.
            for (int blockNo = 0; blockNo < NoOfBlocks; blockNo++)
            {
                // Get the address of the block
                byte* blockAddress = (byte*)StartAddress + checked(blockNo * (long)SizeOfBlock);

                // Work with spans
                Span<byte> blockSpan = new(blockAddress, SizeOfBlock);
                for (int i = 0; i < SizeOfBlock; i++)
                    blockSpan[i] = 0;
                //BlockData.CopyTo(blockSpan);

                // Print the blockNo.
                Console.WriteLine(blockNo);
            };

            Console.WriteLine("Done");

            stream.Dispose();
        }
    }
}
0

There are 0 best solutions below