【发布时间】:2016-02-11 13:41:44
【问题描述】:
我正在尝试使用内存映射文件访问大文件。在研究与标准 I/O 文件访问机制比较的性能时,我注意到一种我目前无法解释的异常行为。
访问带有MemoryMappedFileAccess.ReadWrite 标志的内存映射的3GB 大文件后,再次打开文件大约需要9 秒,即使我只是在文件上打开FileStream。使用MemoryMappedFile 后下次访问文件会很慢。即使没有定义 ViewAccessors,也没有向文件写入任何内容,这种情况也会发生。如果我使用Read 标志创建 MemoryMappedFile,则不会发生此行为,并且下一次打开操作只需大约一毫秒。
我读到在映射不再使用之前可能不会将脏页写入磁盘但考虑到我没有向文件写入任何内容并且该进程是唯一使用内存映射的进程我不明白为什么这仍然发生。
我用这段代码测试过:
static void Main(string[] args)
{
TestFileOpen();
TestMMF();
TestMMF();
TestFileOpen();
TestFileOpen();
TestMMF();
Console.WriteLine("Finished.");
Console.ReadKey();
}
private static void TestMMF()
{
Console.Write("Open Memory Mapped File... ");
const long size = 1024L*1024L*3000L;
Stopwatch sw = Stopwatch.StartNew();
using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
using (MemoryMappedFile.CreateFromFile(stream, "Map", size, MemoryMappedFileAccess.ReadWrite, null, HandleInheritability.None, true))
{
}
Console.WriteLine(sw.Elapsed.TotalSeconds);
}
private static void TestFileOpen()
{
Console.Write("Open File Stream... ");
Stopwatch sw = Stopwatch.StartNew();
using (File.Open(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
{
}
Console.WriteLine(sw.Elapsed.TotalSeconds);
}
这给了我:
Open File Stream... 9,2946138
Open Memory Mapped File... 0,0003105
Open Memory Mapped File... 9,2050714
Open File Stream... 9,2130051
Open File Stream... 0,0001751
Open Memory Mapped File... 0,0001529
Finished.
请注意,使用 FileStream 后的调用会很快,而使用 MemoryMappedFile 后的调用会花费很长时间。 另请注意,第一次调用也需要很长时间,这是因为基准程序中的最后一次调用(应用程序的上一次运行!)访问了带有内存映射的文件。
我错过了什么吗?我可以做些什么来防止这种情况发生吗?
【问题讨论】:
-
这是全部代码吗?你什么都不写吗?捕获这些操作的 procmon.exe 跟踪。有一个持续时间列。让我们看看究竟是什么花费了这么多时间。
-
@usr 是的,就是执行的代码。很好地调用过程监视器。持续时间较长的重复行如下所示:
[...] CreateFile [...] SUCCESS Desired Access: Generic Read/Write, Disposition: OpenIf, Options: Synchronous IO Non-Alert, Non-Directory File, Open No Recall, Attributes: n/a, ShareMode: Read, Write, AllocationSize: 0, OpenResult: Opened 9.3067812其中 9.3067812 是持续时间。 -
根据 procmon 没有其他进程访问该文件。但是我在另一台机器上执行了应用程序,它在那里运行没有问题。我有一种感觉,这可能与我的开发机器上的病毒扫描程序等软件有关......
-
您可以尝试在延迟期间运行 PerfView 来分析机器。 CPU 堆栈视图可能会显示谁在堆栈上。也许你会在那里找到 AV。您需要自己查看系统进程。
-
我根本看不到这方面的证据,甚至在 8 GB 文件上也没有。打开文件需要 10 毫秒,其余时间不到 1 毫秒。这也没有任何意义,这不是 Windows 的工作方式。但它永远被垃圾软件所困扰,禁用您的反恶意软件产品并重试。