MemoryMappedFile与很慢的CreateViewStream
本文关键字:CreateViewStream MemoryMappedFile | 更新日期: 2023-09-27 18:08:33
我使用的内存映射文件大约是。100gb的数据。当我在那个文件上调用CreateViewStream
时,它需要30分钟来创建它,似乎是因为内存映射文件的大小,但是,为什么要花这么长时间?它是否将整个文件复制到托管内存中?
当我用文件流写入文件并在不重新启动的情况下访问它时,需要更长的时间。(奇怪的)
我无法复制这些问题。下面是我用来测试的代码:
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字节。
请提供显示您所描述的行为的示例代码,我很乐意将其分开,看看发生了什么。
如果不了解代码、主存和体系结构,这个问题很难回答。因此,我只能猜测一些重要的指针:
- 你的内存够吗?直接,如果您引用的地址尚未加载到RAM中,则会在后台发生页面错误,并为您将数据读取到RAM中。您的程序不会注意到此活动,因为在处理页面错误时线程被挂起。好文章。
- 同一篇文章中的另一个重要观点—您无法控制中有多少MMF保存在内存中或保存多长时间。这意味着使用MMF可能会将其他东西挤出RAM,例如"很快"需要返回的代码或数据页。从而导致较慢的执行。我特别想指出任何阅读这个答案的人在这里的另一个答案,这样我们就能清楚地知道慢慢在处理器周期方面有多慢。
- 接下来,创建一个流。流适合顺序访问,而您可能试图随机读取/写入。
关于FileStream与MMF方法中代码的端到端运行时间,我认为您应该重新运行测试,因为运行第一种方法可能会导致第二种方法的预热缓存。那么结果就不正确了。
根据MMF的MSDN文档,
内存映射文件使程序员能够处理非常大的文件文件,因为内存可以并发管理,并且它们允许对文件的完全随机访问,而不需要查找。
MMF的工作方式是将文件的整个(或一部分)映射为虚拟内存,当您访问文件的部分时,操作系统透明地将其调入和调出内存。这就是为什么mmf最适合处理大文件的原因。
您可以更聪明地读取整个文件的一部分,并通过使用:
执行随机访问using (var accessor = mmf.CreateViewAccessor(offset, length))
{
//Here you have access to a specific part of the file
}
,以便您可以访问具有指定偏移量和大小的视图,您的猛犸文件的内存映射