Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory mapped file and memory consumption

Given the following test code (x64 environment):

    static void Test()
    {
        string fileName = @"d:\map";
        long length = new FileInfo(fileName).Length;
        using (var file = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open, "mapFile", length, MemoryMappedFileAccess.ReadWrite))
        {
            byte* bytePtr = (byte*)0;
            var view = file.CreateViewAccessor(0, length, MemoryMappedFileAccess.ReadWrite);
            view.SafeMemoryMappedViewHandle.AcquirePointer(ref bytePtr);

            long count = (long)(length / sizeof(int));
            long sum = 0;
            long step =  count / 2000;

            int* ptr = (int*)&bytePtr[0];
            long currentCount = 0 ;

            Parallel.For(0, count, new ParallelOptions { MaxDegreeOfParallelism = 8 }, (i) =>
            {
                Interlocked.Add(ref sum, ptr[i]);
                Interlocked.Increment(ref currentCount) ;

                if (currentCount % step == 0)
                    Console.Write("\r{0:0.00}%", (100 * currentCount / (float)count));
            });

            Console.WriteLine(sum);

            view.Dispose();
        }
    }

Given that "d:\map" is a 40GB file, there is a very odd behavior when there is random access through the pointer "ptr".

System physical memory get fully used, and everything get slowed, with this process taking more than 2 hours to complete.

When I have sequential (and single threaded) access, the physical memory used don't top 1GB and the process takes about 8 minutes.

My question is: When using memory mapped file does the "real" memory get used? Isn't only virtual address space that gets occupied?

I'm trying to understand physical memory consumption when using memory mapped file.

like image 431
Henrique Avatar asked Mar 22 '23 23:03

Henrique


1 Answers

Memory mapped files use virtual memory. You'll have no trouble mapping many more gigabytes of VM space than you have RAM on a 64-bit operating system. The point of a demand-page virtual memory operating system, the sum of the memory required for all running processes always greatly exceeds the amount of RAM.

Mapping it to RAM costs money, that's where the demand comes in to play. The processor interrupts the program and yells for help when it tries to access a virtual memory address that is not mapped to RAM. Called a page fault.

If you did not spend that money on getting at least 40 GB of RAM then you'll inevitably pay the cost of the OS dealing with these page faults. Which requires allocating a RAM page and filling it with the content from the file. Perf go South when it has to unmap previously mapped RAM and save its content to the file. Followed by re-using the freed-up RAM page and loading file content from the appropriate file offset. Very deer, the disk is slow. A problem known as "thrashing".

It is much less of an issue when you address the memory sequentially, one page fault is good for 4096 bytes of sequential access and you'll have good odds that the disk reader head is still in the right spot when you trip a page fault.

like image 87
Hans Passant Avatar answered Apr 26 '23 21:04

Hans Passant