内存映射文件和内存消耗

时间:2013-07-31 22:46:56

标签: c# memory-mapped-files

给出以下测试代码(x64环境):

    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();
        }
    }

鉴于" d:\ map"是一个40GB的文件,当通过指针" ptr"随机访问时,有一种非常奇怪的行为。

系统物理内存得到充分利用,一切都变慢了,这个过程需要2个多小时才能完成。

当我进行顺序(和单线程)访问时,使用的物理内存不会超过1GB,并且该过程大约需要8分钟。

我的问题是:当使用内存映射文件时," real"记忆得到了用?是不是只占用虚拟地址空间?

我在尝试使用内存映射文件时了解物理内存消耗。

1 个答案:

答案 0 :(得分:5)

内存映射文件使用虚拟内存。映射更多GB的VM空间比在64位操作系统上使用RAM没有任何问题。需求页面虚拟内存操作系统的要点,所有正在运行的进程所需的内存总和总是大大超过RAM的数量。

将其映射到RAM会花钱,这就是 demand 的用武之地。当处理器尝试访问未映射到RAM的虚拟内存地址时,处理器会中断程序并大声寻求帮助。称为页面错误

如果您没有花费这笔钱来获得至少40 GB的RAM,那么您将不可避免地支付处理这些页面错误的操作系统的成本。这需要分配一个RAM页面并用文件中的内容填充它。当必须取消映射先前映射的RAM并将其内容保存到文件时,Perf转到South。然后重新使用释放的RAM页面并从适当的文件偏移量加载文件内容。很鹿,盘子很慢。一个被称为“颠簸”的问题。

当你按顺序寻址内存时,问题就不那么严重了,一个页面错误对于4096字节的顺序访问是有利的,当你旅行时,你有很好的机会让磁盘读卡器头仍然在正确的位置。页面错误。