异步/等待与Parallel.For,在这种情况下哪个更好?

5

我需要检查成千上万个项目是否为最新状态。每个项目都需要读取数千个文件(其中某些文件可能在不同的项目中相同)。

目前,使用TPL(async/await)实现此操作,每个要读取的文件和每个要检查的项目都有一个任务。这样做效果很好,但是当我进行性能分析时,第三个最耗费时间的函数是线程池中的TrySteal函数。

使用Visual Studio并发查看器,我发现99%的线程时间都花费在与并发相关的项上,只有1%用于执行。这导致我认为我可能创建了太多的任务(注意:我没有在任何地方使用Task.Run,只有await)。

使用Parellel.For读取一堆文件是否比使用async/await少开销?使用任务编程库会产生多少开销?


你是否检查了资源监视器(可通过Windows任务管理器的性能选项卡获得)以查看您是否达到了磁盘子系统的性能能力?如果是这样,您可能需要重新考虑问题。缓存数据,使用多个驱动器,使用适当的RAID设置,SSD等。 - HABO
可能都不是最好的选择。相反,您可能希望考虑使用_TPL DataFlow_,因为您可以限制每个块中的消息数量,以适合每次I/O操作的数量。 - user585968
2
我有四个硬件RAID的固态硬盘,由于90%的文件已经在内存中,磁盘几乎没有任何升高。然而,CPU使用率在同时运行所有程序时达到了100%,因此我正在尝试通过降低CPU使用率来优化。看起来任务计划程序是其中很大一部分的原因。 - user2460953
1个回答

1
如果您正在检查硬盘上的文件,我认为这项任务并不容易并行化。如果您试图同时读取数千个文件,这只会使进程变得更慢,因为它无法同时读取那么多文件,并且更糟糕的是,它无法将太多文件缓存到内存中。 最快的选择,没有优化检查过程本身,应该只是依次运行它。 如果您真的想要优化它,我建议循环遍历文件,检查每个项目,而不是循环遍历项目,检查每个文件。在这种情况下,即使使用多个线程执行也可能是有效的(但不是全部同时进行)。
更新: 对于当您有足够的内存来缓存所有文件的情况,那么它就不会限制多线程那么多了。仍然建议将并行线程数量限制为与您要使用的处理器核心数量相当的数字。最好使用Parallel.ForEach()实现。此外,Parallel.Foreach()明确指出,您的循环是异步的,因此代码将更易于理解。

在这种情况下,大多数文件都适合存储在内存中(它们很可能已经在内存中)。即使文件已经在内存中,是否仍然适用相同的建议?所谓在内存中,我指的是它们可能在待机列表中,因为它们刚被进程使用过。 - user2460953
@user2460953 不好意思,我的建议不适用了。我已经更新了答案。 - Alex Butenko
由于我有多个项目可能希望读取相同的文件,所以我假设我应该只在表示文件的对象上,在并行for循环内部进行锁定,对吗?这样,如果两个项目想要哈希相同的文件,一个会获胜,另一个会在锁定解决后看到它已经被哈希过了。 - user2460953
@user2460953 很难确定在你的情况下是否进行了有效的优化。但是,如果你正在为每个文件执行相同的任务,为什么不只是制作一个完整的文件列表,然后处理它们(在一个或多个线程中)- 这可能会显着简化逻辑并让你更容易地优化进程。 - Alex Butenko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接