【发布时间】:2019-11-23 20:04:22
【问题描述】:
我正在为应该并行执行耗时(每个请求 50 毫秒)代码的 HTTP 请求创建自定义实现处理程序。我不需要向用户返回任何东西,所以我唯一关心的是在单独的 CPU 内核上快速执行。这是配置实现:
public void Configure(IApplicationBuilder app){
app.Run(context => {
return Task.Run(async () => {
await executeHandle(context);
});
});
}
在每次请求时,都会调用 executeHandle。
private static readonly Object obj = new Object();
public HashSet<string> arrayOfStrings = new HashSet();
public async Task executeHandle(HttpContext context){
if (context.Request.Body != null){
using (var ms = new MemoryStream()){
await Microsoft.AspNetCore.Http.Extensions.StreamCopyOperation.CopyToAsync(
context.Request.Body, ms, s_maxInMemoryData, context.RequestAborted);
var requestBody = ms.ToArray();
string html = Encoding.UTF8.GetString(responseBody);
// inspect arrayOfStrings HashSet on each request and execude logic based on
// items found
// build DOM tree using HTMLAgilePack or some other library, takes 50ms
// should execute in parallel, not just on a separate thread
// call BuildDomTree();
}
}
}
public static void BuildDomTree(){
// build DOM and update HashSet
lock(obj){
arrayOfStrings.add("somestring")
}
}
由于性能在这里很重要,我想听听一些专家对如何调用 BuildDomTree 的意见。请注意,我不会向用户返回任何内容,但仍需要尽快获得结果。一种选择是使用
Task.Run(() => {BuildDomTree()});
这样做的问题是它只在不同的线程上执行,但不一定是并行的。另一种选择是使用Parallel.For 并将其包装在Task.Run 中以避免阻塞:
Task.Run(() => {Parallel.For(0, 1, BuildDomTree)});
我是否考虑过优化?有没有更好的方法来并行执行单个函数?
【问题讨论】:
-
ASP.NET 管道已经是异步的,所以只需
app.Run(context => executeHandle(context));。使用await Task.Run(() => BuildDomTree());以便线程池线程执行它而不是ASP 线程。然后,即使您的服务器可以处理 10 个并发活动请求,您仍然可以有 100 或 1000 个这些请求“运行”,并且线程池的大小将决定有多少BuildDomTrees 实际并行执行。arrayOfStrings看起来需要是静态的。 -
有点相关,考虑使用并发集合来容纳您的
arrayOfStrings。如果您不特别需要HashSet<string>的性能优势,则类似ConcurrentBag<string>的东西会起作用。并发集合是线程安全的,这意味着您无需在添加或读取项目之前手动锁定列表。 -
您确定
BuildDomTree是可并行化的吗?并非所有计算机问题都是embarrassingly parallel。 -
谢谢大家。想法是
BuildDomTree应该在不同的 CPU 上并行运行。它没有什么可并行化的,只是需要不减慢与 executeHandle 正在运行的同一 CPU 上的其他线程。 -
那么您对
Task.Run(() => {BuildDomTree()});的担心是它可能会在不同的线程中调用BuildDomTree方法,而不是在不同的CPU 中?
标签: c# parallel-processing async-await task-parallel-library