磁盘

时间:2015-07-31 12:42:56

标签: c# .net memory io disk-io

我已经阅读了很多关于尝试分配超过1GB内存的SO帖子和一般文章,所以在拍摄之前就像其他人一样,这是一些背景。

此应用程序将作为自助服务终端运行,其中专用计算机不会运行任何不必要的进程。

我的应用程序从高速相机获取图像,滚动快门的速度为每秒120帧,分辨率为1920 x 1080,位深度为24.应用程序需要将每一帧写入磁盘后期处理。我面临的当前问题是磁盘I / O不会跟上捕获率,即使它限制在每秒120帧。所需的磁盘I / O带宽约为750MBps!

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

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

  • 通过将硬件级别的位深度降低到16(仍然大约为500MBps)来降低质量。
  • 禁用所有图像编码并将原始相机数据写入磁盘。这节省了一些处理时间。
  • 在磁盘上创建一个10GB的文件,并在帧进入时执行顺序直写。到目前为止,这已经帮助最多了。所有开发和生产系统都有一个100GB的专用驱动器用于此应用程序。
  • 使用Sysinternals中的Contig.exe对文件进行碎片整理。这在非SSD驱动器上获得了惊人的增长。

在这里探索的选项。我不熟悉内存映射文件,在尝试创建它们时,我得到一个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可用空间上运行。但是,并非所有生产系统都有SSD驱动器。

3 个答案:

答案 0 :(得分:1)

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

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

贵公司计划花多少钱开发和测试软件以推动廉价硬件超越其限制?即使你能够让它足够快地工作,他们计划花多少钱来维护这个软件呢?

答案 1 :(得分:1)

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

  2. 如果您有一个大文件,通常不会尝试将其完全映射到RAM中...您映射它的“窗口”,然后“移动”窗口(在C#/ Windows API中创建从任何一个位置开始并具有特定大小的文件的“视图”

  3. 代码示例:(此处窗口大1mb ...更大的窗口是可能的......在32位时,应该可以分配64或128mb窗口而没有任何问题)

    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)...你的代码应该是不同的(因为你不能预先知道“确切” fileSize)。还记得:内存映射文件不会加速写入文件

答案 2 :(得分:1)

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

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

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