是否值得同步 I/O 密集型线程以提高总磁盘性能?

Posted

技术标签:

【中文标题】是否值得同步 I/O 密集型线程以提高总磁盘性能?【英文标题】:Is it worth synchronizing I/O intensive threads in order to increase total disk performance? 【发布时间】:2015-04-19 19:06:39 【问题描述】:

我们的 Windows .NET 应用程序有多个 I/O 密集型线程,它们不断地写入磁盘(旋转介质)。来自一个线程的写操作是在它不知道另一个线程的写操作的情况下完成的,因此这意味着写请求以与恰好执行调用相同的顺序到达 Windows I/O 管理器。

我们的项目中已经讨论过这是否是正确的方法,或者我们是否可以通过同步写入操作来获得一些性能,以便只有一个(或几个)线程执行写入操作同时到磁盘(可能通过共享锁)。从理论上讲,这会减轻 CPU 的压力,并为我们提供更好的吞吐量(请注意,我们已经在所有操作中使用异步 I/O)。

我对整个想法有点怀疑,因为我认为我们将完成操作系统最初旨在解决的部分工作。现在已经进行了一些实验,它指出了根本没有任何好处的方向。我的印象是,只要缓冲区大小足够,何时将块写入磁盘的决定最好留给操作系统来决定。

那么有人可以启发我们吗?从多线程进程同步磁盘访问以获得性能是一个好主意吗?例如,Windows 或 Linux 在这方面有什么不同吗?

【问题讨论】:

您正在编写的文件有多大?数据总共有多大? 在这个用例中,我们不断地写入磁盘,当文件达到一定大小时,我们关闭它们并开始一个新的,所以每个可能 50 MB。总数可能是可用磁盘的 75%。这完全取决于保留时间。 这对于写入来说不是那么重要,因为操作系统可以延迟和电梯排序它们。如果同时发出不相关的读取和刷新,则会导致真正的性能问题,因为磁盘最终花费的时间比实际执行 I/O 的时间更多。 当然,所有这些问题对于不需要搜索的固态驱动器来说都变得微不足道了。 【参考方案1】:

理论上是这样可以减少 CPU 的压力

怎么可能?写入次数相同,但现在增加了同步。它会产生(一点)更多的 CPU 负载。

然后,我们将完成操作系统最初旨在解决的部分工作。

遗憾的是,Windows 无法执行任何类型的智能 IO 调度。我不确定磁盘驱动程序是做什么的。对于 NCQ 和 SATA,肯定会有一定程度的操作重新排序。但我从未观察到 Windows 在 IO 方面做了一些智能的事情(除了预取效果很好)。

主要问题是您是要执行顺序 IO 还是随机 IO。

    顺序:多个顺序流导致 Windows 将流分成 64KB 或 256KB 的块,使它们高度随机。这真是太可怕了。在这种情况下,您可以通过智能地发出大型 IO 来获得数量级的性能。 随机:一次发出许多 IO,以便磁盘硬件可以重新排序它们。例如,SQL Server 有时会发出数千个问题(并在此期间完全阻止其他进程 - 请注意这一点。Windows 没有实际可行的 IO 公平概念。)

我对 Linux 了解不多,但至少它某种 IO 调度。 Windows 团队似乎不想解决这个问题。

【讨论】:

在 SSD 上这应该无关紧要,但在 HDD 上,我经常注意到两个并发的顺序 IO 操作由于它们之间的大量不必要的查找而彼此减慢了很多。但由于这些通常是文件副本,因此是读取和写入的混合,我不确定纯写入在多大程度上是正确的,可以缓冲。 @CodesInChaos 试试看。从一个卷复制到下一个卷,并使用具有高级输出的 procmon 查看物理 IO。它不漂亮。通常,NTFS 甚至会完美交错地分配集群,从而导致最大碎片。因此,除了低效的 IO 调度之外,我们还在 NTFS 层获得了最大的碎片。在这里很难找到任何积极的方面。 另外,这在 SSD 上也很重要,因为随机 SSD IO 比顺序慢 10 倍。对于磁盘,它是 100 倍。 如果我离开的印象是最好的做法是尽可能多地进行处理,然后在最后将其全部写出来,而不是将所有内容写成我去? @jpmc26 最好的办法是确保 IO 是顺序的。对于未缓存的 IO:只要单个 IO 足够大以保证磁盘搜索,您可以以涓涓的方式写入数据,没问题。缓存 IO:您可以毫无问题地进行涓流写入。写入首先进入 Windows 缓存,然后在后台以大顺序写入刷新。

以上是关于是否值得同步 I/O 密集型线程以提高总磁盘性能?的主要内容,如果未能解决你的问题,请参考以下文章

测试 C++ 代码的性能

linux 服务器I/O读写测试

python多线程使用场景

Nodejs密集型CPU解决方案

使用线程池和BlockingQueue重新构建I / O密集型Java Web服务

使用内存磁盘进行 I/O 单元测试