使用内存映射文件的缺点

4

我的网络服务每分钟写入数千个交易,我们将它们保存在硬盘上。

我正在测试不同的文件保存方式,我使用标准IO和内存映射文件进行了一些测试。在我的测试结果中,使用内存映射文件写入文件(20 k文本文件)比标准IO快约4倍,并且我没有找到任何缺点。

由于我对这项技术没有太多经验,您认为我使用它们可能会遇到任何问题吗?或者您认为没有任何缺点?

谢谢!

编辑1,以下是源代码:

namespace FileWritingTests.Writers {
    public class MappedFileWriter : ITestWriter {
        public void Write(string content, string path,string id) {
            Byte[] data = System.Text.Encoding.UTF8.GetBytes(content);

            using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None))

            using (MemoryMappedFile memoryMapped = MemoryMappedFile.CreateFromFile(fileStream, id, data.Count(),
                MemoryMappedFileAccess.ReadWrite, new MemoryMappedFileSecurity(), HandleInheritability.Inheritable, true)) {
                var viewStream = memoryMapped.CreateViewStream();
                viewStream.Write(data, 0, data.Length);                       
            }
        }
    }
}

而这是测试人员:

  public TimeSpan Run(int iterations, Writers.ITestWriter tester, String subfolder) {
            Console.WriteLine(" -- Starting test {0} with {1} file writings",subfolder, iterations.ToString());

            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Reset();
            stopWatch.Start();
            for (int i = 1; i <= iterations; i++) {
                tester.Write(transaction, this.path + "\\" + subfolder + "\\" + "file_" + i.ToString() + ".txt", i.ToString());
            }
            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;

            Console.WriteLine(" -- finish test {0} with {1} file writings. Time Elapsed: {2}", subfolder, iterations.ToString(), ts.TotalMilliseconds);
            return ts;
        }

测试人员被多次调用,而且有几种不同类型的测试人员进行比较。


如果程序或计算机崩溃,我会担心文件内容会发生什么。 - AdrianHHH
只是一个想法/提示/思路:最近我对MMF进行了一些测试,但除了崩溃问题外,我不喜欢预先设置文件大小的想法(Hans写道这并不是必须的 - 我猜我从来没有达到那个点)。最终,我使用了由ESENT数据库支持的PersistentDictionary和快速序列化(protobuf)。将两者结合起来,应用程序现在能够同步处理20000多条记录每秒,并且速度接近MMF。 - Linky
我之前遇到过电脑崩溃和文件不完整的问题,但在我的情况下更糟糕。我需要一个好的文件或者没有文件。如果没有文件,我可以使用数据库回滚之前的交易...但是损坏的文件对我来说很糟糕。 - Rafa
1
对我来说也是一样,但我认为内存映射文件损坏的机会比PersistentDictionary/Esent db更高,因为后者会写入其日志。这可能值得一看:http://managedesent.codeplex.com/ - Linky
1个回答

17
MMF的主要缺点是它们会占用RAM,使文件系统缓存的效果降低。对于如此小的文件不是问题。
另一个缺点,虽然肯定是故意的,就是您不能再测量编写文件的成本了。这现在是内核完成的工作,而不是您的程序。当然仍在进行中,没有免费的午餐。它与您程序的其余执行并发,所谓的自由线程。在任务管理器中密切关注“系统”进程的CPU利用率。对于如此小的文件,这也是极不可能成为问题。
这是一种微观优化,被创建文件的成本所淹没。在磁盘驱动器上徘徊在20到50毫秒之间。不要忘记将其包括在您的测量中。写入文件数据以内存总线速度运行,取决于机器上的RAM类型,高达5 GB / s。您削减的只是低级WriteFile()调用,现在由内核完成。可以尝试使用接受bufferSize值的构造函数来测试FileStream。默认值为4096字节,请将其增加到32K,以便仅进行一个WriteFile()调用。以这种方式操作的首要优点是您不必事先猜测MMF的大小。如果您猜得太低,情况会变得非常丑陋。

感谢您的提示,我将在我的问题中添加用于测试的代码以及我计划在服务器上使用的代码。 - Rafa

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