c– 实时写入磁盘

c– 实时写入磁盘,第1张

概述我有一个线程需要将数据从内存缓冲区写入磁盘数千次.我对每次写入需要多长时间有一些要求,因为需要清除缓冲区以便单独的线程再次写入它.我用dd测试了磁盘.我没有在其上使用任何文件系统并直接写入磁盘(使用direct标志打开它).我能够以32K块大小获得大约100 MB / s.在我的应用程序中,我注意到我无法以接近此速度将数据写入磁盘.所以我调查了发生了什么,我

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

我用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延迟.

总结

以上是内存溢出为你收集整理的c – 实时写入磁盘全部内容,希望文章能够帮你解决c – 实时写入磁盘所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/1046866.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存