磁盘上连续的内存映射文件

Memory mapped files that are contiguous on disk

我已经阅读了很多关于尝试分配超过 1GB 内存的 SO posts 和一般文章,所以在像其他人一样被击落之前,这里有一些上下文。

此应用程序将 运行 作为带有专用机器的信息亭 运行 没有不必要的进程。

我的应用程序以每秒 120 帧的速度、分辨率为 1920 x 1080、位深度为 24 的速度从卷帘快门高速相机获取图像。该应用程序需要将每一帧写入到post-处理的磁盘。我目前面临的问题是磁盘 I/O 无法跟上捕获率,即使它被限制为每秒 120 帧。磁盘 I/O 所需带宽约为 750MBps!

原始格式的录制总长度需要至少 10 秒 (7.5GB)。执行任何即时转码或压缩都会将帧速率降低到完全无法接受的水平。

为了解决这个问题,我尝试了以下方法:

此处没有可供探索的选项。我不熟悉内存映射文件,在尝试创建它们时,我得到一个 IOException 说 Not enough storage is available to process this command..

using (var file = MemoryMappedFile.CreateFromFile(@"D:\Temp.VideoCache", FileMode.OpenOrCreate, "MyMapName", int.MaxValue, MemoryMappedFileAccess.CopyOnWrite))
{
    ...
}

我目前使用的大文件需要顺序写入访问或顺序读取访问。任何指针将不胜感激。

如果只有一种方法可以分配那么多 RAM,我什至可以将整体记录大小强制降低到 1.8GB。再一次,这将 运行 在具有 8GB 可用内存和 100GB 可用内存 space 的专用内存上。但是,并非所有生产系统都具有 SSD 驱动器。

商品硬件便宜是有原因的。您需要更快的硬件。

购买更快的磁盘系统。一个好的 RAID 控制器和四个 SSD。将驱动器放入 RAID 1+0 配置并解决此问题。

贵公司计划花费多少资金来开发和测试软件以推动廉价硬件突破其局限性?即使您能让它运行得足够快,他们计划花费多少来维护该软件?

  1. 内存映射文件不会加快写入文件的速度...

  2. 如果你有一个大文件,你通常不会尝试将它完全映射到 RAM 中......你映射它的 "window",然后 "move" window(在 C#/Windows API 中,您创建文件的 "view" 从任何一个位置开始并具有特定大小)

代码示例:(这里 window 是 1mb 大...更大 windows 是可能的...在 32 位应该可以分配 64 或 128mb window 没问题)

const string fileName = "Test.bin";
const long fileSize = 1024L * 1024 * 16;
const long windowSize = 1024 * 1024;

if (!File.Exists(fileName)) {
    using (var file = File.Create(fileName)) {
        file.SetLength(fileSize);
    }
}

long realFileSize = new FileInfo(fileName).Length;

if (realFileSize < fileSize) {
    using (var file = File.Create(fileName)) {
        file.SetLength(fileSize);
    }
}

using (var mm = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open)) {
    long start = 0;

    while (true) {
        long size = Math.Min(fileSize - start, windowSize);

        if (size <= 0) {
            break;
        }

        using (var acc = mm.CreateViewAccessor(start, size)) {
            for (int i = 0; i < size; i++) {
                // It is probably faster if you write the file with
                // acc.WriteArray()
                acc.Write(i, (byte)i);
            }
        }

        start += windowSize;
    }
}

请注意,我在这里编写的代码将写入固定的已知字节数 (fileSize)...您的代码应该不同(因为您无法预先知道 "exact" fileSize)。还记得:内存映射文件不会加快写入文件的速度

32位进程在64位系统上可以分配4GB的RAM,所以应该可以得到1.8GB的RAM来存储视频,当然你需要考虑加载的DLL和缓冲区,直到视频已压缩。

除此之外,您可以使用 RAMDisk,例如来自 DataRam。您只需要在应用程序需要多少内存和您可以授予磁盘多少内存之间找到平衡。恕我直言,5 GB / 3 GB 的设置可能效果很好:1 GB 用于 OS,4 GB 用于您的应用程序,3 GB 用于文件。

如果您希望文件持久保存,请不要忘记将文件从 RAM 磁盘复制到 HDD。