【发布时间】:2018-02-27 09:17:38
【问题描述】:
我用谷歌搜索了很多,但恐怕我不完全理解并发和并行的后果。
我有大约 3000 行数据库对象,每个对象平均附加了 2-4 个逻辑数据,这些数据需要作为搜索查询的一部分进行验证,这意味着验证服务需要执行大约3*3000次。例如。用户已经过滤了颜色,然后每一行都需要验证颜色并返回结果。找到匹配项后循环不会中断,这意味着始终需要评估所有逻辑对象(这是由于计算相关性而不是匹配项)。
这是在用户选择各种属性时按需完成的,这意味着性能是这里的关键。
我目前正在使用 Parallel.ForEach 执行此操作,但想知道使用异步行为是否更聪明?
当前方式
var validatorService = new LogicalGroupValidatorService();
ConcurrentBag<StandardSearchResult> results = new ConcurrentBag<StandardSearchResult>();
Parallel.ForEach(searchGroups, (group) =>
{
var searchGroupResult = validatorService.ValidateLogicGroupRecursivly(
propertySearchQuery, group.StandardPropertyLogicalGroup);
result.Add(new StandardSearchResult(searchGroupResult));
});
异步示例代码
var validatorService = new LogicalGroupValidatorService();
List<StandardSearchResult> results = new List<StandardSearchResult>();
var tasks = new List<Task<StandardPropertyLogicalGroupSearchResult>>();
foreach (var group in searchGroups)
{
tasks.Add(validatorService.ValidateLogicGroupRecursivlyAsync(
propertySearchQuery, group.StandardPropertyLogicalGroup));
}
await Task.WhenAll(tasks);
results = tasks.Select(logicalGroupResultTask =>
new StandardSearchResult(logicalGroupResultTask.Result)).ToList();
【问题讨论】:
-
由于您似乎实现了这两个版本,如果您测量两个版本的执行时间会是什么样子?
-
您衡量性能差异了吗?这是唯一确定的方法。也就是说,我的猜测是在这种情况下并行应该表现更好,因为异步主要是“在等待其他系统时不要阻塞主线程”
-
那么 ValidateLogicGroupRecursivly 是与数据库一起工作还是一切都在内存中完成?
-
对于 3000 或 9000 行,这无关紧要,除非您正在对数据库进行一些往返或每行的任何 CPU 繁重的工作都无关紧要。循环 9000 次迭代来计算一些简单的公式或值对于今天的计算机来说不算什么。除非您已经测量了现实世界的瓶颈问题,否则只需在单个线程上执行即可。在 ASP.NET Core 中启动/排队太多线程实际上可能会降低整体性能而不是提高整体性能(ASP.NET Core 在用完(排队)线程时在高流量情况下开始拒绝连接)
-
如果您必须对数据库进行任何往返,可能有更好的方法来解决它(在代码中找出您需要的值,然后在一个查询中获取所有值,然后在本地执行计算) (重 CPU 意味着每行 1-2 毫秒,因此整个计算需要 9 到 18 秒。今天 CPU 上的典型计算在 ns 范围内,因此 9000 条记录如果需要 1 或 2 则没有太大区别毫秒)
标签: c# asynchronous asp.net-core parallel.foreach