c – 实时写入磁盘

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

我用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.这太长了,无法满足我的应用程序的要求.我不认为这可以完全归因于磁盘的旋转延迟.有什么想法,我可以做些什么来获得更稳定的写入速度?谢谢

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

最佳答案
我假设您正在使用连接到标准计算机中的内置磁盘控制器的ATA或SATA驱动器.这是一个有效的假设,还是你使用任何不寻常的东西(硬件RAID控制器,SCSI驱动器,外部驱动器等)?

作为一名在工作中进行大量磁盘I / O性能测试的工程师,我会说这听起来很像你的写入被缓存在某个地方.您的“高延迟”I / O是最终刷新缓存的结果.即使没有文件系统,I / O操作也可以缓存在I / O控制器或磁盘本身中.

为了更好地了解正在发生的事情,不仅要记录最大延迟,还要记录平均延迟.考虑记录最多10-15个延迟样本,以便更好地了解这些高延迟样本的频率(in-).另外,丢弃测试前两三秒内记录的数据,然后开始数据记录.在磁盘测试开始时可能会出现高延迟的I / O操作,这些操作并不表示磁盘的真实性能(可能是因为磁盘必须加速到全速,头部不得不这样做一个大的初始搜索,刷新的磁盘写缓存等).

如果您想要对磁盘I / O性能进行基准测试,我建议使用像IOMeter这样的工具,而不是使用dd或滚动自己的工具. IOMeter可以很容易地看出它改变I / O大小,对齐等有什么不同,而且它可以跟踪许多有用的统计信息.

要求I / O操作在一定时间内发生是一件危险的事情.首先,系统上的其他应用程序可以与您竞争磁盘访问或CPU时间,几乎不可能预测它们对I / O速度的确切影响.您的磁盘可能遇到坏块,在这种情况下,它必须做一些额外的工作来重新映射受影响的扇区,然后再处理I / O.这引入了不可预测的延迟.您也无法控制操作系统,驱动程序和磁盘控制器正在执行的操作.出于任何不可预见的原因,您的I / O请求可能会在其中一个层中备份.

如果您对I / O时间有硬限制的唯一原因是因为正在重新使用缓冲区,请考虑更改算法.尝试使用循环缓冲区,以便在写入数据时可以从中清除数据.如果您发现填充它比冲刷它更快,则可以减少缓冲区的使用量.或者,您也可以创建多个缓冲区并循环使用它们.当一个缓冲区填满时,将该缓冲区写入磁盘并切换到下一个缓冲区.即使第一个仍在写入,您也可以写入新缓冲区.

回复评论:
你不能真正“让内核脱离”,它是系统中的最低级别,你必须在某种程度上经历它.您可以为磁盘控制器构建自定义版本的驱动程序(前提是它是开源的),并构建一个“高优先级”I / O路径供应用程序使用.您仍然受磁盘控制器固件和驱动器本身的固件/硬件的支配,您无法预测或执行任何操作.

传统上,硬盘驱动器在执行大型顺序I / O操作时表现最佳.驱动程序,设备固件和OS I / O子系统将此考虑在内,并尝试将较小的I / O请求组合在一起,以便它们只需向驱动器生成单个大型I / O请求.如果您一次只刷新32K,那么您的写入可能会在某个级别缓存,合并,并立即发送到驱动器.通过消除这种合并,您应该减少I / O延迟“峰值”的数量,并看到更均匀的磁盘访问时间.但是,这些访问时间将更接近您的“峰值”所见的大时间,而不是您通常看到的温和时间.延迟峰值对应于未与任何其他人合并的I / O请求,因此必须吸收磁盘搜索的整个开销.请求合并是出于某种原因;通过捆绑请求,您将通过多个命令分摊驱动器查找操作的开销.击败合并会导致执行比正常情况更多的搜索操作,从而降低I / O速度.这是一种权衡:您可以减少平均I / O延迟,但代价是偶尔会出现异常的高延迟操作.然而,这是一种有益的权衡,因为与禁用合并相关的平均延迟的增加几乎总是比具有更一致的访问时间的优点更不利.

我还假设您已经尝试调整线程优先级,并且这不是您的高带宽生产者线程在缓冲区缓冲线程中耗尽CPU时间的情况.你确认了吗?

你说你不想打扰同时在系统上运行的高带宽线程.您是否实际测试了各种输出缓冲区大小/数量并测量了它们对另一个线程的影响?如果是这样,请分享您测量的一些结果,以便我们在头脑风暴时可以使用更多信息.

考虑到大多数机器具有的内存量,从32K缓冲区移动到通过4个32K缓冲区旋转的系统是内存使用量的一个相当无关紧要的跳跃.在具有1GB内存的系统上,缓冲区大小的增加仅占系统内存的0.0092%.尝试移动到交替/旋转缓冲区系统(保持简单,从2开始)并测量对高带宽线程的影响.我打赌额外的32K内存不会对另一个线程产生任何明显的影响.这不应该是生成器线程的“弄脏缓存”.如果您经常使用这些内存区域,则应始终将它们标记为“正在使用”,并且永远不应将其换出物理内存.刷新的缓冲区必须保留在物理内存中才能使DMA工作,而第二个缓冲区将在内存中,因为您的生产者线程当前正在写入它.确实,使用额外的缓冲区将减少生产者线程可用的物理内存总量(虽然只是非常轻微),但如果您运行的是需要高带宽和低延迟的应用程序,那么您可以将系统设计为它有超过32K的内存空间.

通过尝试强制硬件和低级软件执行特定性能测量来解决问题,更简单的解决方案是调整软件以适应硬件.如果您将最大写入延迟测量为1秒(为了获得良好的整数),请编写程序,以便刷新到磁盘的缓冲区不需要重新使用至少2.5-3秒.这样你可以覆盖最糟糕的情况,并提供安全边际以防万一出现意外情况.如果使用旋转3-4个输出缓冲区的系统,则不必担心在刷新之前重新使用缓冲区.您无法过于密切地控制硬件,如果您已经写入原始卷(没有文件系统),那么您与可以操作或消除的硬件之间并不多.如果您的程序设计不灵活且您看到不可接受的延迟峰值,您可以尝试更快的驱动器.固态硬盘不必“寻求”进行I / O操作,因此您应该看到相当统一的硬件I / O延迟.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


linux常用进程通信方式包括管道(pipe)、有名管道(FIFO)、信号(signal)、消息队列、共享内存、信号量、套接字(socket)。管道用于具有亲缘关系的进程间通信,有名管道的每个管道具有名字,使没有亲缘关系的进程间也可以通信。信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除
Linux性能观测工具按类别可分为系统级别和进程级别,系统级别对整个系统的性能做统计,而进程级别则具体到进程,为每个进程维护统计信息。&#xD;&#xA;&#xD;&#xA;按实现原理分,可分为基于计数器和跟踪以及剖析。含义如下:&#xD;&#xA;&#xD;&#xA;计数器:内核维护的统计数据,通常为无符号整型,用于对发生的事件计数,比如,网络包接收计数器,磁
本文详细介绍了curl命令基础和高级用法,包括跳过https的证书验证,详细追踪整个交互过程,可用于调用网络后端接口,诊断http和https网络服务故障。
本文包含作者工作中常用到的一些命令,用于诊断网络、磁盘占满、fd泄漏等问题。命令包括ping、fping、tcpdump、lsof、netstat、/proc/$pid/fd、du、grep、traceroute、dig。
linux的平均负载表示运行态和就绪态及不可中断状态(正在io)的进程数目,用uptime查看到负载很高,既有可能是CPU利用率高,也可能是大量在等待io的进程导致,用mpstat查看每个CPU的使用情况,查看CPU的使用率或者CPU花在等待io的时间,接着用pidstat定位具体的进程
CPU上下文频繁切换会导致系统性能下降,切换分为进程切换、线程切换及中断切换,进程切换的开销较大,除了需要保存寄存器和程序计数器中的值还需保存全局变量、栈等到内存中,以便下次运行恢复,而同一进程中的线程切换开销会小很多,只需更新寄存器和线程独有的栈,共享资源如打开的文件、全局变量等无需切换,当硬件中
1.top命令 作用:该命令可以按CPU使用.内存使用和执行时间对任务进行排序,常用来监控系统中占用CPU或内存较高的程序及CPU和内存的负载。 默认视图: 当想看系统负载时,可观察汇总的%CPU中的us用户进程和sy系统进程是否占用CPU很高,相加接近100%就说明占用很高了,有些程序可能得不到及
文章浏览阅读1.8k次,点赞63次,收藏54次。Linux下的目录权限!!!粘滞位!!!超详解!!!
文章浏览阅读1.6k次,点赞44次,收藏38次。关于Qt的安装、Windows、Linux、MacBook_mack book 安装qt
本文介绍了使用shell脚本编写一个 Hello
文章浏览阅读1.5k次,点赞37次,收藏43次。【Linux】初识Linux——了解操作系统的发展历史以及初次体验Linux编程环境
文章浏览阅读3k次,点赞34次,收藏156次。Linux超详细笔记,个人学习时很认真的记录的,觉得好的麻烦点个赞。
文章浏览阅读6.8k次,点赞109次,收藏114次。【Linux】 OpenSSH_9.3p1 升级到 OpenSSH_9.5p1(亲测无问题,建议收藏)_openssh_9.5p1
文章浏览阅读3.5k次,点赞93次,收藏78次。初识Linux中的线程,理解线程的各种概念,理解进程地址空间中的页表转换,介绍pthread线程库并理解线程库!
文章浏览阅读863次。出现此问题为Linux文件权限问题,解决方案为回到引擎目录执行命令。输入用户密码后运行./UnrealEditor。_increasing per-process limit of core file size to infinity.
文章浏览阅读2.9k次。使用文本编辑器:打开CSV文件,并使用文本编辑器(如Notepad++、Sublime Text、Visual Studio Code等)来查看文件的字符编码格式。通常在编辑器的底部状态栏或设置中可以找到当前编码的显示。请注意,上述方法并非绝对准确,特别是当文件没有明确的编码标识时。因此,如果你发现CSV文件在不同的工具或方法中显示不同的编码格式,可能需要进行进一步的分析和判断,或者尝试使用不同的编码转换方法。该命令将输出文件的MIME类型和编码信息。使用命令行工具:在命令行中,你可以使用。_shell读取csv文件逐行处理
本文介绍了如何在Linux系统中升级gcc版本,以便更好地支持C++11及以上版本的新特性。通过升级gcc,可以提升编译器的功能和性能,获得更好的开发体验。详细的步骤和方法请参考原文链接。
文章浏览阅读4.4k次,点赞6次,收藏19次。Mosquitto是一个开源的MQTT消息代理服务器。MQTT是一个轻量级的、基于发布/订阅模式的消息传输协议。 mosquitto的安装使用比较简单,可以方便的来进行一些测试。_linux mosquitto
文章浏览阅读7.2k次,点赞2次,收藏12次。Linux中,用于根目录下有一个.ssh目录,保存了ssh相关的key和一些记录文件。_~/.ssh/
文章浏览阅读4.5k次,点赞5次,收藏18次。首先需要安装 snmp ,使用下面的命令进行安装安装完毕之后,使用下面的命令查看是否安装成功当命令行显示如图即为安装成功。_snmp工具