MemoryMappedFile具有非常慢的CreateViewStream

时间:2015-08-19 06:15:31

标签: c# memory-mapped-files

我正在使用大约的内存映射文件。 100 GB的数据。当我在该文件上调用CreateViewStream时,创建它需要30分钟,而且由于内存映射文件的大小,它似乎是,但为什么要花这么长时间? 它是否将整个文件复制到托管内存中?

使用文件流编写文件并在不重新启动的情况下访问它需要更长的时间。 (奇怪的)

2 个答案:

答案 0 :(得分:4)

我无法复制这些问题。这是我用来测试的代码:

    static void Main(string[] args)
    {
        var sw = Stopwatch.StartNew();
        var mmf = MemoryMappedFile.CreateFromFile(@"f:\test.bin");
        var stream = mmf.CreateViewStream();
        for (int i = 0; i < 100000; i++)
        {
            stream.ReadByte();
        }
        Console.WriteLine(sw.Elapsed);
    }

f:\test.bin是我为此测试生成的100GB零填充文件。我能够创建MemoryMappedFile,然后运行CreateViewStream并在3.7秒内从中读取100,000个字节。

请提供展示您所描述行为的示例代码,我很乐意将其拆开并查看发生了什么。

答案 1 :(得分:3)

如果没有代码,主内存和架构知识,这是一个很难回答的问题。因此,我只能猜出一些重要的指示:

  1. 你有足够的RAM吗?直接关闭,如果你提到一个尚未加载到RAM中的地址,会在幕后发生页面错误并将数据读入RAM。您的程序没有注意到此活动,因为在处理页面错误时您的线程被挂起。好文章here
  2. 同一篇文章的另一个重点 - 您无法控制内存中保留多少MMF 或持续多长时间。这意味着使用MMF可能会将其他内容从RAM中推出,例如“很快”需要的代码或数据页。从而导致执行速度变慢。我特别想要将任何读过这个答案的人指向another answer here,这样我们就可以清楚地了解这种缓慢程度与处理器周期有关。
  3. 接下来,您正在创建一个流。 Streams 适合顺序访问,而您可能正在尝试随机读取/写入
  4. 关于FileStream与MMF方法中代码的端到端运行时间,我认为您应该重新运行测试,因为运行第一个方法可能会导致预热缓存第二个。结果不会是正确的。

    根据MSDN documentation of MMF

      

    内存映射文件使程序员能够使用极大的工作   文件,因为内存可以同时管理,他们允许   完整,随机访问文件而无需搜索。

    MMF的工作方式是将文件的整个(或部分)映射为虚拟内存,当您访问文件的某些部分时,操作系统会透明地分页进出内存。这就是为什么MMF首先适合处理大文件的原因。

    您可以更聪明地阅读整个文件的一部分,并通过以下方式执行随机访问:

    using (var accessor = mmf.CreateViewAccessor(offset, length))
    {
        //Here you have access to a specific part of the file
    }
    

    这样您就可以访问具有指定偏移量和大小的视图,这是您庞大文件的内存映射。