Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 对磁盘的实时写入_C_Linux_Real Time - Fatal编程技术网

C 对磁盘的实时写入

C 对磁盘的实时写入,c,linux,real-time,C,Linux,Real Time,我有一个线程需要将数据从内存缓冲区写入磁盘数千次。我有一些关于每次写入所需时间的要求,因为需要清除缓冲区,以便一个单独的线程再次写入 我已经用dd测试了磁盘。我没有在磁盘上使用任何文件系统,也没有直接写入磁盘(用direct标志打开磁盘)。我能够以32K的块大小获得大约100MB/s 在我的应用程序中,我注意到我无法以接近这个速度将数据写入磁盘。所以我调查了当时发生的事情,我发现有些写作需要很长时间。我的代码块如下所示(顺便说一下,这是C语言): last=get_timestamp(); wr

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

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

在我的应用程序中,我注意到我无法以接近这个速度将数据写入磁盘。所以我调查了当时发生的事情,我发现有些写作需要很长时间。我的代码块如下所示(顺便说一下,这是C语言):

last=get_timestamp();
write();
现在=获取时间戳();
如果(最长写入<现在-最后)
最长写入=现在-最后;
最后我打印出最长的字迹。我发现对于32K缓冲区,最长写入速度约为47ms。这太长了,无法满足我的应用程序的要求。我认为这不能完全归因于磁盘的旋转延迟。有什么想法吗?我能做些什么来获得更稳定的写入速度?谢谢

编辑:
事实上,我使用了我上面声明的多个缓冲区,并将它们分条到多个磁盘。我的问题的一个解决方案是增加缓冲区的数量,以分摊长写操作的成本。但是,我希望将用于缓冲的内存量保持尽可能小,以避免弄脏正在生成写入缓冲区的数据的线程的缓存。我的问题应该局限于处理将小数据块写入磁盘的延迟差异以及如何减少它。

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

dd的最大区别可能是查找时间,dd流式传输到连续(大部分)块列表,如果您正在写入大量小文件,则头部可能会在整个驱动器中查找以分配它们

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

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

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

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

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

通常,磁盘I/O不是针对延迟进行优化的,而是针对吞吐量进行优化的。高延迟是正常现象,而网络文件系统的延迟甚至更高

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

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

注意:如果要查看实际速度,请在打开文件时尝试设置
O\u DSYNC
标志

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

100MB/s,带
dd
——无需任何同步——是一个高度综合的基准测试,因为您永远不知道数据真正进入了磁盘。尝试将
conv=dsync
添加到
dd
的命令行

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

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

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

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

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

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

否则,只有当您的应用程序是磁盘的唯一用户时,才能实现(旋转)磁盘I/O的某种实时性。(实时应用程序的旧规则适用:只能有一个。)
O_DIRECT
有助于从等式中消除操作系统本身的影响。(尽管由于文件扩展的块分配,文件系统的开销仍会以偶尔的延迟形式出现。在Linux下运行速度很快,但仍然可以通过预先分配整个文件来避免,例如通过写零点。)如果时间非常重要,考虑购买专用磁盘来进行工作。固态硬盘具有优良的thr性能
last = get_timestamp();
write();
now = get_timestamp();
if (longest_write < now - last)
  longest_write = now - last;