将数据写入文件:fflush()需要花费很多时间

时间:2011-07-07 07:26:08

标签: c optimization io video-processing buffering

我有一个要求,我必须缓冲大量数据(以GB为单位),以备将来使用。 由于没有足够的RAM可用于缓冲如此大量的数据,我决定将数据存储在一个文件中。

现在的缺陷是,当我将数据写入文件时,其他线程可能需要“缓冲”数据,因此每次我写入内容时都必须刷​​新文件流。确切地说,数据是我作为预先记录的数据缓冲的视频帧(如TiVo) 和其他线程可能会或可能不想在任何给定的时间点写它,但是当它们这样做时,它们fread来自文件并处理帧。

在一般情况下,fwrite - fflush组合大约需要150美元,但偶尔(并且相当规律),组合需要超过1.5秒。我无法负担这一点,因为我必须实时处理帧。

我在这里有很多问题:

  1. 我在文件中缓冲数据的方法是否正确?我有什么替代品?

  2. 知道为什么fwrite-fflush操作在某些情况下会突然花费更多时间吗?请注意,它在1.5秒后恢复到150 us。

2 个答案:

答案 0 :(得分:2)

对于#2:大多数现代文件系统使用btree方法来管理当今巨大的HD中的目录和数据节点的数量。与所有btree一样,它们有时需要平衡。当发生这种情况时,不会发生任何变化,这就是系统锁定的原因。通常情况下,由于操作系统的巨大缓存,这并不是什么大不了的事情,但你是一个很痛苦的角落。

你能做些什么?有两种方法:

  1. 使用套接字进行通信并将最后N帧保留在RAM中(即永远不要将它们写入磁盘或使用独立进程将其写入磁盘)。

  2. 不要写新文件,覆盖现有文件。由于所有数据块的位置都是预先知道的,因此在写入时FS中不会有重组。它也会快一点。因此,我们的想法是创建一个巨大的文件或使用原始分区,然后覆盖它。当您点击文件末尾时,请回到开头并重复。

  3. 缺点:

    使用方法#1,您可以丢失帧数。此外,您必须确保所有客户端都能够足够快地读取和处理数据,否则服务器可能会阻止。

    使用#2,您必须找到一种方法告诉读者当前“文件结束”的位置。

    所以也许混合方法最好:

    1. 创建一个巨大的文件(几GB)。如果一个文件不够,请创建几个。
    2. 打开套接字
    3. 将数据写入文件。如果到达文件末尾,请寻找位置0并继续写入(如循环缓冲区)。
    4. 刷新数据
    5. 通过套接字
    6. 将新数据的开头和数量发送给读者

      考虑使用内存映射文件;这将使一切变得更加简单。

答案 1 :(得分:1)

除了RAM和磁盘外,实际上没有任何其他选项,只有变体。我认为这种方法很合理:你的文件系统性能非常好。

额外的偶然时间很可能是由于文件系统寻找更多可用空间(它保留了一个短列表,但是当用尽时,需要更昂贵的搜索)并将其分配到文件中。如果这是原因,请以最大大小预分配文件,并使用随机i / o(fopen (fn, "r+"))写入文件,以便它不会截断文件长度。

另一种可能有助于稳定文件i / o时间的技术是将每个帧缓冲区写入与扇区边界对齐的文件偏移量。这样,文件系统不必处理奇怪的偏移写操作,首先从扇区读取以保留不会被覆盖的内容。