【问题标题】:Do the I/O parallelism truly gives so much perfomance?I/O 并行性真的提供了如此多的性能吗?
【发布时间】:2014-03-11 13:04:24
【问题描述】:

stackoverflow 上有很多问题:IO 应该使用多少线程? 答案是一个,如果 CPU 不忙,或者你会有开销。

我测试我发现这根本不是真的,或者我的测试代码可能是错误的。让我们试试 使用 .NET 同步和异步复制大文件:

class Program
{
    const string UserDirectory = @"C:\testDir\";
    const string sourceFile1 = UserDirectory + "1.rar";
    const string sourceFile2 = UserDirectory + "2.rar";
    const string dstFile1 = UserDirectory + "1copy.rar";
    const string dstFile2 = UserDirectory + "2copy.rar";

    static void Main(string[] args)
    {
        Clear();

        var watch = Stopwatch.StartNew();

        StdCopySync();
        Console.WriteLine("Standart copy Sync complited in {0} ms", watch.ElapsedMilliseconds);

        Clear();
        Thread.Sleep(1000);
        watch.Restart();

        StdCopyAsync();
        Console.WriteLine("Standart copy Async complited in {0} ms", watch.ElapsedMilliseconds);
    }

    private static void Clear()
    {
        File.Delete(dstFile1);
        File.Delete(dstFile2);
    }


    private static void StdCopySync()
    {
        File.Copy(sourceFile1, dstFile1);
        File.Copy(sourceFile2, dstFile2);
    }

    private static void StdCopyAsync()
    {

        Task t1 = new Task(() =>
        {
            File.Copy(sourceFile1, dstFile1);
        });

        Task t2 = new Task(() =>
        {
            File.Copy(sourceFile2, dstFile2);
        });

        t1.Start();
        t2.Start();
        Task.WaitAll(new List<Task>() { t1, t2 }.ToArray());
    }
}

平均结果让我大吃一惊。 (5 个测量,sourceFile1 与 sourceFile2 相同,大小接近 1GB)

  • 单硬盘,Windows 7:异步速度提高 16%
  • SSD,Windows 8:异步速度提高 5%
  • RAID 0,Windows 8:异步速度提高 40%。 (但为什么这么多?为什么控制器和内核没有按预期并行工作?)

我也试过不使用标准文件。复制文本并将其写入文件 usync .NET Async 构造 - 结果相同。

所以我得出一个结论,最佳一致性水平应该通过自适应算法进行搜索。并且 2 个同时 IO 请求总是比 1 个更好。你同意吗?

【问题讨论】:

  • 请注意,异步与线程无关。
  • @SLaks 是的,谢谢。我的意思是同时的 IO 请求。已更正。
  • 在做IO的时候,需要做的就是保持磁盘硬件忙于读/写。线程对此无济于事。
  • 我怀疑你的测量结果。每个尝试在 Windows 资源管理器中同时复制多个大文件的人都知道事实并非如此。我们需要找出您的测量有什么问题或您的设置有什么特别之处。
  • 这些测试是出了名的不可靠,根本不测试 I/O 速度。只是内存总线带宽,由文件系统缓存使用。非常快,只是内存到内存的复制。在每次测试运行之前,首先使用 SysInternals 的 RAMMap 实用程序刷新缓存。并且确保只使用单个线程进行测试,当线程开始争夺磁盘并强制它来回压缩时,使用多个线程非常会降低速度。尽管 Windows 中的文件复制引擎尝试对此做一些事情,但版本很重要。

标签: c# multithreading performance asynchronous io


【解决方案1】:

当您在一个磁盘上运行多个顺序 IO 流时,您会得到随机 IO。性能完全坦克。

为什么这里不是这样?我怀疑您的文件足够小以适合内存/缓存。您的所有工作都受 CPU 限制。甚至写入也会延迟刷新到磁盘。

您有 4 个文件,每个文件 1GB。您的机器可能有 >4GB 的 RAM。

将文件大小增加 10 倍,性能将完全下降。你会听到你的磁盘从所有磁盘寻道中疯狂地嘎嘎作响。

使用 Process Monitor,您可以看到 Windows(非常不幸)向交错的底层磁盘发出 256KB IO。这对于实现顺序性能来说太小了。

我在这里重复我的评论:

我怀疑你的测量结果。每个尝试在 Windows 资源管理器中同时复制多个大文件的人都知道事实并非如此。我们需要找出您的测量有什么问题或您的设置有什么特别之处。

换句话说,您的基准并未衡量您的想法。

【讨论】:

    【解决方案2】:

    IO 操作将受 IO 限制,而不是 CPU 限制。 CPU 操作将受 CPU 限制。

    对于 IO 操作,您不应该将 CPU 资源用尽。如果你这样做了,你就没有一个 IO 绑定操作,你有一个 CPU 绑定操作。

    IO 操作,如果它们通过适当的异步 API 公开,则不需要任何线程There is no thread。如果您只有同步 API,那么您需要尽可能多的线程来保持任何 IO 介质的最大容量。这可能是一个线程、两个线程或数百个线程。

    一旦达到基于 IO 的资源(无论是硬盘、数据库、网络连接等)的利用率接近 100% 的程度,添加额外的线程也无济于事。事实上,它有时甚至会受到伤害。例如,硬盘针对顺序访问进行了高度优化。并行化通常会导致更多的随机访问,这实际上会导致性能显着降低。

    【讨论】:

      【解决方案3】:

      异步在 RAID 上要快得多,因为它利用了更多的设备并行性。只有非常快的基于 PCI-E 的 SSD 才会有更多的 I/O 线程为您带来更高的性能数字(以使 PCI 带宽饱和)。对于大多数情况而言,具有更好的 I/O 深度(确实发出更大的 I/O)将为您带来更好的性能。

      【讨论】:

        猜你喜欢
        • 2016-08-12
        • 1970-01-01
        • 2011-09-17
        • 2011-05-07
        • 2012-08-06
        • 2013-11-12
        • 2014-05-19
        • 1970-01-01
        • 2013-02-05
        相关资源
        最近更新 更多