MemoryMappedFile创建CreateViewStream非常慢

5
我正在使用一个大约100GB的内存映射文件。当我在该文件上调用CreateViewStream时,需要30分钟才能创建它,看起来是因为内存映射文件的大小,但是为什么要花这么长时间呢?它是否将整个文件复制到托管内存中?
如果我使用文件流写入文件并在没有重新启动的情况下访问它,则需要更长的时间。(奇怪的是)

文件在哪里? - Lasse V. Karlsen
在本地SSD驱动器上 - Sebastian
1
你需要整个文件的视图吗?如果不需要,可以通过传递偏移量和长度仅在所需部分创建视图 - using(var accessor = mmf.CreateViewAccessor(offset, length)) - displayName
5
你没有提供代码,我们该如何评估? - Sam Axe
@Sebastian:你能告诉我在文件的一部分上创建viewaccessor会发生什么吗?而不是整个文件。 - displayName
2个回答

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字节。

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


我认为你应该在for循环中做更多的事情,而不仅仅是一个ReadByte。编译器可能已经优化了循环,因此你能够在3.7秒内运行循环。这只是我的猜测,我可能是错的。 - displayName
1
@displayName:我已经删除了测试文件。我可以重新创建它并对其进行任何操作,但这并不重要。声明是调用CreateViewStream()很昂贵(在他的系统上需要很长时间),但是我已经证明,对于大文件而言,它本身并不那么昂贵(至少对于我的系统而言)。他需要提供更多代码以便其他人能够评估他的声明。 - willaien
嗯...看起来问题可能出在操作者的内存/架构上。 - displayName
1
读取100kb需要3.7秒,这是一项昂贵的操作,速度非常慢。 - Matt

3

没有代码、内存和架构方面的了解,很难给出准确答案。因此,我只能猜测几个重要的指针:

  1. 您是否有足够的RAM? 如果您引用尚未加载到RAM中的地址,则会在后台发生页错误,并为您读取数据到RAM中。当处理页错误时,您的程序不会注意到此活动,因为您的线程被挂起。这里有一篇好文章here
  2. 来自相同文章的另一个重要点 - 您无法控制有多少MMF保留在内存中或保留多长时间。这意味着使用MMF可能会将其他东西推出RAM,例如代码或数据页面,您很快就需要它们回来。从而导致执行速度变慢。我特别想将任何阅读此答案的人指向another answer here,以便我们清楚地了解这种缓慢性在处理器周期方面有多慢。
  3. 接下来,您正在创建一个流。 适用于顺序访问,而您可能正在尝试随机读/写它。

关于FileStream vs MMF方法的端到端运行时间,我认为您应该重新运行测试,因为运行第一种方法可能会导致第二种方法的缓存热身。然后结果将不正确。

根据MSDN文档中MMF的说明

内存映射文件使程序员能够使用极大的文件,因为内存可以并发管理,并且它们允许对文件进行完全、随机访问,而无需寻找。

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

您可以更聪明地读取整个文件的一部分,并通过利用以下方法进行随机访问:

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接