c# - 在 Parallel.ForEach 循环中进行异步数据库调用会提高性能吗?
问题描述
使用 Parallel.ForEach 时,将任何 DB 或 Api 调用转换为异步方法会提高性能吗?
一点背景知识,我目前有一个控制台应用程序,它顺序循环遍历一堆文件,并为每个文件调用一个 API 并进行一些 DB 调用。主要逻辑如下所示:
foreach (file in files)
{
ReadTheFileAndComputeAFewThings(file);
CallAWebService(file);
MakeAFewDbCalls(file);
}
目前所有的 DB 和 Web 服务调用都是同步的。
Parallel.ForEach
正如您所期望的那样,更改要使用的循环给了我巨大的性能提升。
我想知道我是否将Parallel.ForEach
调用保留在那里,并在循环内,将所有 Web 服务调用更改为异步(例如,HttpClient.SendAsync
)并将数据库调用更改为异步(使用 Dapper,db.ExecuteAsync()
) - 这会通过允许它来提高应用程序的性能吗重用线程?或者它会像处理线程分配一样有效地什么都不Parallel.ForEach
做?
解决方案
答案是否定的。异步提供可扩展性,而不是性能。它允许使用更少的内存(每个阻塞线程 = 1 MB浪费的内存)来完成相同的工作。
不过,重要的是要记住,异步性并不是针对单个操作的性能优化。采用同步操作并使其成为异步操作总是会降低该操作的性能,因为它仍然需要完成同步操作所做的所有事情,但现在有额外的限制和考虑因素。
该类Parallel
适用于 CPU 密集型作业。对于部分或完全 I/O 绑定的作业,最好使用异步 API,并且理想情况下独立处理 CPU 绑定和 I/O 绑定部分,因为它们的最佳并发级别通常不同。TPL Dataflow库是此类工作的一个近乎完美的工具。您可以创建相互链接的 Dataflow 块管道,并且每个块都可以配置不同的MaxDegreeOfParallelism
. 对于受 CPU 限制的部分,您受到运行应用程序的机器的处理器/内核数量的限制。对于 I/O 绑定部分,您受到远程 Web 服务器、磁盘驱动器或数据库服务器的功能的限制。
推荐阅读
- css - Facebook 分享按钮右对齐
- c++ - 找不到make,我该如何解决?
- excel - VBA中的递归序列
- java - Eureka 实例应用程序名称不适用于 Spring Cloud Gateway
- javascript - 如何向我的数组的 i、i+1 和 i+2 添加 3 个不同的数字
- eclipse - 如何将上下文菜单条目添加到 Eclipse 编辑器上下文菜单
- javascript - 无法单击单选按钮 - 赛普拉斯
- crash - 不知道,我的游戏一直在手机上崩溃 - 空指针取消引用
- c# - Unity2D 平滑过渡上下移动对象
- reactiveui - 具有 Redux 样式状态的 ReactiveUI