2015-08-19 250 views
5

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

当我用文件流写入文件并在不重新启动的情况下访问文件需要很长时间。 (奇怪)

+0

该文件位于何处? –

+0

在本地ssd驱动器 – Sebastian

+1

您是否需要查看整个文件?如果没有,只需通过传递一个偏移量和长度来创建所需部分的视图''使用(var accessor = mmf.CreateViewAccessor(offset,length))' – displayName

回答

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

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

+0

我认为你应该做更多的东西,而不仅仅是'for'循环中的'ReadByte'。编译器可能已经优化了循环,因此您可以在3.7秒内运行循环。只是我的猜测,我可能是错的。 – displayName

+1

@displayName:我已经删除了测试文件。我可以重新创建它,并且做任何事情,但是这并不重要。声明是,对'CreateViewStream()'的调用是昂贵的(并且在他的系统上花费了非常长的时间),但是,我已经证明它本身对于大文件而言并不昂贵至少不适合我自己的系统)。他需要为任何人提供更多的代码来评估他的主张。 – willaien

+0

嗯......看起来像OPs RAM /架构是问题。 – displayName

3

这是一个难以回答的问题,没有代码,您的主内存和体系结构知识。因此我只能猜出一些重要的指标:

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

关于你的代码中的FileStream VS MMF方法的终端到终端的运行时间,我想你应该重新运行测试,因为运行你的第一种方法威力结果在热身缓存第二一。那么结果将不正确。

按照MSDN documentation of MMF

内存映射文件允许程序员非常大 文件的工作,因为内存可以同时管理,和他们允许无需 齐全,随机访问文件求。

方式MMF工作原理是,该文件的全部(或一部分)被映射为虚拟存储器,这是在进出存储器由OS作为你访问该文件的部分寻呼透明。这就是为什么MMF首先能处理大文件的原因。

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

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

,让你有机会获得一个视图与庞大文件的指定偏移和大小,存储器映射。