我有一个要求,我必须缓冲大量数据(以GB为单位),以备将来使用。 由于没有足够的RAM可用于缓冲如此大量的数据,我决定将数据存储在一个文件中。
现在的缺陷是,当我将数据写入文件时,其他线程可能需要“缓冲”数据,因此每次我写入内容时都必须刷新文件流。确切地说,数据是我作为预先记录的数据缓冲的视频帧(如TiVo)
和其他线程可能会或可能不想在任何给定的时间点写它,但是当它们这样做时,它们fread
来自文件并处理帧。
在一般情况下,fwrite
- fflush
组合大约需要150美元,但偶尔(并且相当规律),组合需要超过1.5秒。我无法负担这一点,因为我必须实时处理帧。
我在这里有很多问题:
我在文件中缓冲数据的方法是否正确?我有什么替代品?
知道为什么fwrite-fflush操作在某些情况下会突然花费更多时间吗?请注意,它在1.5秒后恢复到150 us。
答案 0 :(得分:2)
对于#2:大多数现代文件系统使用btree方法来管理当今巨大的HD中的目录和数据节点的数量。与所有btree一样,它们有时需要平衡。当发生这种情况时,不会发生任何变化,这就是系统锁定的原因。通常情况下,由于操作系统的巨大缓存,这并不是什么大不了的事情,但你是一个很痛苦的角落。
你能做些什么?有两种方法:
使用套接字进行通信并将最后N帧保留在RAM中(即永远不要将它们写入磁盘或使用独立进程将其写入磁盘)。
不要写新文件,覆盖现有文件。由于所有数据块的位置都是预先知道的,因此在写入时FS中不会有重组。它也会快一点。因此,我们的想法是创建一个巨大的文件或使用原始分区,然后覆盖它。当您点击文件末尾时,请回到开头并重复。
缺点:
使用方法#1,您可以丢失帧数。此外,您必须确保所有客户端都能够足够快地读取和处理数据,否则服务器可能会阻止。
使用#2,您必须找到一种方法告诉读者当前“文件结束”的位置。
所以也许混合方法最好:
考虑使用内存映射文件;这将使一切变得更加简单。
答案 1 :(得分:1)
除了RAM和磁盘外,实际上没有任何其他选项,只有变体。我认为这种方法很合理:你的文件系统性能非常好。
额外的偶然时间很可能是由于文件系统寻找更多可用空间(它保留了一个短列表,但是当用尽时,需要更昂贵的搜索)并将其分配到文件中。如果这是原因,请以最大大小预分配文件,并使用随机i / o(fopen (fn, "r+")
)写入文件,以便它不会截断文件长度。
另一种可能有助于稳定文件i / o时间的技术是将每个帧缓冲区写入与扇区边界对齐的文件偏移量。这样,文件系统不必处理奇怪的偏移写操作,首先从扇区读取以保留不会被覆盖的内容。