实时写入磁盘

时间:2010-08-19 19:10:17

标签: c linux real-time

我有一个线程需要将数据从内存缓冲区写入磁盘数千次。我有一些要求,每个写入需要多长时间,因为需要清除缓冲区以便单独的线程再次写入。

我用dd测试了磁盘。我没有在其上使用任何文件系统并直接写入磁盘(使用direct标志打开它)。我能够以32K的块大小获得大约100 MB / s的速度。

在我的应用程序中,我注意到我无法以接近此速度将数据写入磁盘。所以我调查了发生了什么,我发现有些写作花了很长时间。我的代码块看起来像(顺便说一句是C语言):

last = get_timestamp();
write();
now = get_timestamp();
if (longest_write < now - last)
  longest_write = now - last;

最后我打印出最长的写字。我发现对于32K缓冲区,我看到最长的写入速度约为47ms。这太长了,无法满足我的应用程序的要求。我不认为这可以完全归因于磁盘的旋转延迟。有什么想法,我可以做些什么来获得更稳定的写入速度?谢谢

编辑: 我实际上使用了上面我声明的类型的多个缓冲区,并将它们之间的条带化为多个磁盘。我的问题的一个解决方案是增加缓冲区的数量以分摊长写入的成本。但是,我想保持用于缓冲的内存量尽可能小,以避免弄乱产生写入缓冲区的数据的线程的缓存。我的问题应该局限于处理将小块写入磁盘的延迟的变化以及如何减少它。

5 个答案:

答案 0 :(得分:8)

答案 1 :(得分:2)

只要您使用O_DIRECT | O_SYNC,就可以使用ioprio_set()来设置进程/线程的IO调度优先级(尽管手册页上写着“进程”,我相信您可以通过由gettid())给出的TID。

如果您设置了实时IO类,那么您的IO将始终首先访问磁盘 - 听起来这就是您想要的。

答案 2 :(得分:1)

  

我有一个线程需要将数据从内存缓冲区写入磁盘数千次。

     

我用dd测试了磁盘。我没有在其上使用任何文件系统并直接写入磁盘(使用direct标志打开它)。我能够以32K的块大小获得大约100 MB / s的速度。

dd的块大小与文件系统块大小一致。我想你的日志文件不是。

另外,您的应用程序可能不仅会写入日志文件,还会执行其他一些文件操作。或者您的应用程序不仅仅是使用磁盘。

通常,磁盘I / O未针对延迟进行优化,而是针对吞吐量进行了优化。高延迟是正常的 - 网络文件系统使它们更高。

  

在我的应用程序中,我注意到我无法以接近此速度将数据写入磁盘。所以我调查了发生的事情,发现有些写作花了很长时间。

有些写入需要更长的时间,因为在一段时间后,您使写入队列饱和,操作系统最终决定将数据实际刷新到磁盘。默认情况下,I / O队列配置得很短:避免因崩溃导致的过度缓冲和信息丢失。

N.B。如果您想查看真实的速度,请在打开文件时尝试设置O_DSYNC标志。

如果你的块确实是对齐的,你可以尝试使用O_DIRECT标志,因为这会删除Linux磁盘缓存级别上的争用(与其他应用程序)。写入将以磁盘的实际速度工作。

100MB / s dd - 没有任何同步 - 是一个高度合成的基准测试,因为你永远不知道数据确实击中了磁盘。尝试将conv=dsync添加到dd的命令行。

还尝试使用更大的块大小。 32K仍然很小。当我几年前测试顺序与随机I / O时,IIRC 128K大小是最佳的。

  

我看到最长的写入速度约为47毫秒。

“实时”!=“快”。如果我将最大响应时间定义为50毫秒,并且您的应用程序在50毫秒(47 <50)内持续响应,那么您的应用程序将被归类为实时。

  

我认为这不能完全归因于磁盘的旋转延迟。任何想法是什么以及我可以做些什么来获得更稳定的写入速度?

我认为你不能避免write()延迟。延迟是磁盘I / O的继承属性。你无法避免它们 - 你必须期待和处理它们。

我只能考虑以下选项:使用两个缓冲区。第一个将由write()使用,第二个 - 用于存储来自线程的新传入数据。当write()完成时,切换缓冲区,如果有要写的东西,开始写它。这样,线程总是有一个缓冲区来放入信息。如果线程生成的信息比write()写入的速度快,则可能仍会发生溢出。动态添加更多缓冲区(达到某个限制)可能会有所帮助。

否则,只有当您的应用程序是磁盘的唯一用户时,才能为(旋转)磁盘I / O实现某种实时性。 (实时应用程序的旧规则适用:只能有一个。)O_DIRECT有助于以某种方式消除操作系统本身对等式的影响。 (虽然由于文件扩展名的块分配,你仍然会有偶然延迟的文件系统开销。在Linux下工作得非常快,但仍可以通过提前预先分配整个文件来避免,例如写入零。 )如果时间非常重要,请考虑购买专用磁盘。固态硬盘拥有出色的吞吐量,不会受到影响。

答案 3 :(得分:0)

您是在写新文件还是覆盖同一个文件?

与dd的巨大差异可能是寻求时间,dd正在流式传输到一个有条件的(大部分)块列表,如果你正在编写大量小文件,那么头部可能会在整个驱动器上寻找分配它们。 / p>

解决问题的最佳方法可能是删除在特定时间内写入日志的要求。您是否可以使用一组缓冲区,以便在新的日志数据到达另一个缓冲区时写入(或至少发送到驱动器的缓冲区)?

答案 4 :(得分:0)

linux不会直接将任何内容写入磁盘,而是会使用虚拟内存,然后,内核线程pdflush将这些数据写入磁盘,可以通过sysctl -w“”