当前位置:  开发笔记 > 编程语言 > 正文

C#:具有大量I/O的多线程性能不佳

如何解决《C#:具有大量I/O的多线程性能不佳》经验,为你挑选了3个好方法。

我在C#中编写了一个应用程序,它将jpgs从一组目录同时移动到另一组目录(每个固定子目录一个线程).代码看起来像这样:

        string destination = "";
        DirectoryInfo dir = new DirectoryInfo("");
        DirectoryInfo subDirs = dir.GetDirectories();
        foreach (DirectoryInfo d in subDirs)
        {
            FileInfo[] files = subDirs.GetFiles();
            foreach (FileInfo f in files)
            {
                f.MoveTo(destination);
            }
        }

但是,应用程序的性能是可怕的 - 大量的页面错误/秒.每个子目录中的文件数量可能会非常大,所以我认为一个很大的性能损失来自一个上下文切换,它不能同时将所有不同的文件阵列保存在RAM中,这样它就会进入磁盘几乎每一次.

我能想到两种不同的解决方案.第一种是用C或C++重写它,第二种是使用多个进程而不是多线程.

编辑:文件根据时间戳命名,它们移动到的目录基于该名称.因此,它们被移动到的目录将对应于它创建的小时; 例如3-27-2009/10.

我们正在为每个目录创建一个后台工作程序用于线程.

有什么建议?



1> jason saldo..:

经验法则,不要将操作与串行依赖关系并行化.在这种情况下,您的硬盘驱动器是瓶颈,许多线程只会让性能变差.

如果要使用线程,请尝试将数量限制为可用资源数,核心数和硬盘数不是您要挂起的作业数,要复制的目录数.



2> Jon Skeet..:

重新考虑答案

我一直在重新考虑下面的原始答案.我仍然怀疑使用更少的线程可能是一个好主意,但是因为你只是移动文件,它实际上不应该是IO密集型.只列出文件可能会占用大量磁盘.

但是,我怀疑你的文件内存真的不足.你有多少记忆力?这个过程占用了多少内存?您使用了多少个线程,以及您拥有多少个核心?(使用明显多于核心的线程是一个坏主意,IMO.)

我建议采取以下攻击计划:

找出实际存在瓶颈的地方.尝试获取文件列表但不进行移动.查看磁盘有多难以及需要多长时间.

尝试不同数量的线程,目录队列仍在处理中.

密切关注内存使用和垃圾收集.CLR的Windows性能计数器对此有好处.

原始答案

用C或C++重写无济于事.使用多个流程无济于事.你正在做的就是给一个处理器一百个线程 - 除了你用磁盘代替它.

这是有道理的parallelise其使用IO如果有任务,涉及计算相当数量的,但如果它已经盘的约束,要求盘有很多,同时文件的工作只会让事情变得更糟.

您可能对我最近运行的基准测试(描述和初始结果)感兴趣,测试文件各行的"加密".当"加密"级别较低时(即它几乎不做任何CPU工作),最好的结果始终是单个线程.



3> sipwiz..:

如果您的工作块依赖于系统瓶颈,在本例中是磁盘IO,那么最好不要使用多个线程或进程.您最终将要做的就是在等待磁盘时产生大量额外的CPU和内存活动.如果您使用单个线程进行移动,您可能会发现应用程序的性能得到改善.

推荐阅读
和谐啄木鸟
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有