C# 使用内存映射文件的缺点

C# 使用内存映射文件的缺点,c#,.net,performance,.net-4.0,memory-mapped-files,C#,.net,Performance,.net 4.0,Memory Mapped Files,我的web服务每分钟写入数千个事务,我们将它们保存在hd上 我正在测试保存这些文件的不同方法,并使用标准IO和内存映射文件进行了一些测试。在我的结果中,使用MemoryMapped文件编写文件(20K文本文件)比标准IO快4倍左右,我没有发现任何缺点 由于我对这项技术没有太多的经验,你认为我在使用它们时会遇到任何问题吗?或者你看不到任何缺点 谢谢 编辑1,来源如下: namespace FileWritingTests.Writers { public class MappedFileW

我的web服务每分钟写入数千个事务,我们将它们保存在hd上

我正在测试保存这些文件的不同方法,并使用标准IO和内存映射文件进行了一些测试。在我的结果中,使用MemoryMapped文件编写文件(20K文本文件)比标准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;
        }
公共时间跨度运行(int迭代,Writers.ITestWriter测试程序,字符串子文件夹){ WriteLine(“--用{1}文件写入启动测试{0}”,子文件夹,iterations.ToString()); 秒表秒表=新秒表(); 秒表复位(); 秒表。开始();
对于(int i=1;i而言,MMF的主要缺点是它们会消耗RAM,从而降低文件系统缓存的效率。对于这样小的文件来说,这不是问题

另一个缺点,虽然肯定是故意的,但是您不能再衡量编写文件的成本。现在这是一项由内核完成的工作,而不是由您的程序完成。当然,这项工作仍在进行中,没有免费的午餐。它与您的程序的其余部分执行并行,免费线程,以便speak、 注意任务管理器中“系统”进程的CPU利用率。同样,这样的小文件不太可能出现问题


这是一个微型优化,被创建文件的成本冲垮了。在主轴磁盘驱动器上,它徘徊在20到50毫秒之间。别忘了在测量中包括这一点。写入文件数据的速度是内存总线速度,高达5千兆字节/秒,这取决于机器的RAM类型。您剪切的只是低内存-级别WriteFile()调用,它们现在由内核完成。您可以尝试使用FileStream进行测试,使用接受bufferSize值的构造函数。默认值为4096字节,将其增加到32K,以便只有一个WriteFile()调用。这样做的主要优点是,你不必预先猜测MMF的大小。如果你猜得太低,它会变得非常难看。

我会担心如果程序或计算机崩溃,文件内容会发生什么变化。只是一个想法/提示/想法:我最近在MMF上运行了一些测试,但除了崩溃问题之外,我不知道取消了预先设置文件大小的想法(Hans写道,这并不是所有方面都需要的——我想我从来没有达到这一点)。最后,我使用了一个由ESENT数据库支持的PersistentDictionary和一个快速序列化(protobuf)。将两者结合起来,应用程序现在能够每秒同步处理20000多条记录,速度非常接近MMF。我已经遇到了计算机崩溃和文件不完整的问题,这在我的情况下更糟。我需要一个好文件或没有文件。没有文件,我可以使用db…b回滚以前的事务ut损坏的文件对我来说不好。对我来说也是一样,但在我看来,在编写日志时,内存映射文件中的文件损坏几率要高于PersistentDictionary/Esent db。这可能值得一看:谢谢你的提示,我将在我的问题中添加我在测试中使用的代码,以及我计划用于服务器的代码。