MemoryMappedFiles:可以为文件分配多少内存

时间:2011-04-01 19:44:03

标签: c# memory memory-management dynamic-memory-allocation

我有大量的CT rawdata文件,最大可能超过20到30GB。对于我们当前部门中的大多数计算机,我们最多只有3GB。但是为了处理数据,我们需要查看所有可用数据。当然,我们可以通过读写函数顺序遍历数据来实现这一点。但有时需要将一些数据保存在内存中。

目前我有自己的内存管理,我创建了一个所谓的MappableObject。每个rawdatafile包含20000个结构,每个结构显示不同的数据。每个MappableObject都引用文件中的一个位置。

在C#中,我创建了一个部分工作的机制,如果需要,它会自动打开和取消映射数据。从几年前我就知道了MemoryMappedFiles,但是在.NET 3.5中我拒绝使用它,因为我在.NET 4.0中知道它可以原生使用。

所以今天我尝试了MemoryMappedFiles,发现不可能分配多少内存。如果我有一个32位系统,并且我想分配20GB,由于超出逻辑地址空间的大小,它不起作用。这对我来说是清楚的。

但有没有办法像我一样处理这么大的文件?我还有什么机会?你们是如何解决这些问题的?

由于 马丁

4 个答案:

答案 0 :(得分:3)

我所知道的唯一限制是您可以映射的文件的最大视图的大小,该视图受地址空间的限制。内存映射文件可能大于地址空间。 Windows需要在进程的地址空间的连续块中映射文件视图,因此最大映射的大小等于最大空闲地址空间块的大小。文件系统本身强加了对文件总大小的唯一限制。

看一下这篇文章:Working with Large Memory-Mapped Files

答案 1 :(得分:2)

“内存映射”,您无法将20千兆字节映射到2千兆字节的虚拟地址空间。在32位操作系统上获得500 MB是非常棘手的。请注意,除非您需要对文件数据进行大量随机访问,否则它不是是一个很好的解决方案。当你必须对视图进行分区时,哪个应该很难。通过常规文件的顺序访问是非常适度的内存使用。还要注意从MMF编组数据的成本,你仍然需要支付托管结构的副本编组成本。

答案 2 :(得分:1)

你仍然可以按顺序读取文件,你只能在内存中存储2GB以上的数据。

您可以一次映射文件的块,最好是块结构的倍数。

例如。文件是32GB。内存映射一次32MB的文件并解析它。一旦你到达那32MB的末尾,映射下一个32MB的文件并继续,直到你到达文件的末尾。

我不确定最佳映射大小是什么,但这是一个如何完成它的示例。

答案 3 :(得分:0)

你是对的。我首先尝试使用没有文件的memorymapped文件。在那里它不起作用。如果我有一个现有的文件。我可以映射我想要的内存。我想在没有真实文件的情况下使用MemoryMappedFiles的原因是它应该在流处理时自动删除。 MemoryMappedFile不支持此功能。

我现在看到的是我可以执行以下操作来获得预期结果:

       // Create the stream
        FileStream stream = new FileStream(
            "D:\\test.dat", 
            FileMode.Create, 
            FileAccess.ReadWrite, 
            FileShare.ReadWrite, 
            8, 
            FileOptions.DeleteOnClose // This is the necessary part for me.
            );

        // Create a file mapping
        MemoryMappedFile x = MemoryMappedFile.CreateFromFile(
            stream,
            "File1", 
            10000000000, 
            MemoryMappedFileAccess.ReadWrite, 
            new MemoryMappedFileSecurity(),
            System.IO.HandleInheritability.None, 
            false
            );

        // Dispose the stream, using the FileOptions.DeleteOnClose the file is gone now
        stream.Dispose();

至少在查看第一个结果时,我看起来很好。

谢谢。