我有一个要求,其中我必须缓冲大量数据(以 GB 为单位)以供将来使用。
由于没有足够的 RAM 来缓冲如此大量的数据,我决定将数据存储在文件中。
现在的陷阱是,当我将数据写入文件时,其他线程可能需要“缓冲”数据,因此每次向文件流写入内容时,我都必须刷新文件流。准确地说,数据是我缓冲为预先录制的数据的视频帧(如 TiVo)
其他线程可能想也可能不想在任何给定的时间点写入它,但是当它们这样做时,它们fread
从文件中并处理帧。
在一般情况下,fwrite
-fflush
连击大约需要 150 秒,但偶尔(并且相当经常),连击需要超过 1.5 秒。我负担不起,因为我必须实时处理帧。
我在这里有很多问题:
我在文件中缓冲数据的方法是否正确?我还有哪些选择?
知道为什么 fwrite-fflush 操作在某些情况下突然需要更多时间吗?请注意,一次花费 1.5 秒后,它会恢复到 150 us。
至于#2:大多数现代文件系统使用 btree 方法来管理当今巨大硬盘中的目录和数据节点数量。与所有 B 树一样,它们有时需要平衡。当这种情况发生时,不得进行任何更改,这就是系统锁定的原因。通常,这不是什么大问题,因为操作系统有巨大的缓存,但你是一个会受到伤害的极端情况。
你能为这个做什么?有两种方法:
使用套接字进行通信并将最后 N 帧保留在 RAM 中(即永远不要将它们写入磁盘或使用独立进程将其写入磁盘)。
不要写入新文件,覆盖现有文件。由于所有数据块的位置都是预先知道的,因此在写入时 FS 中不会进行重组。它也会快一点。因此,我们的想法是创建一个大文件或使用原始分区,然后覆盖它。当您到达文件末尾时,返回到开头并重复。
缺点:
使用方法#1,您可能会丢失帧。此外,您必须绝对确保所有客户端都可以足够快地读取和处理数据,否则服务器可能会阻塞。
对于#2,您必须找到一种方法来告诉读者当前的“文件结尾”在哪里。
所以也许混合方法是最好的:
- 创建一个巨大的文件(几 GB)。如果一个文件不够,请创建多个。
- 打开一个套接字
- 将数据写入文件。如果到达文件末尾,则寻找位置 0 并继续在那里写入(就像循环缓冲区一样)。
- 刷新数据
- 通过套接字将新数据的开始和数量发送给阅读器
考虑使用内存映射文件;这将使一切变得更加简单。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)