提高并行消息传递性能(TPL / Async)



我有一个性能优化问题,已经困扰我一段时间了。我曾试图从它身上挤出更多的性能,但收效甚微。

系统(简化)如下:

1)请求通过HTTP Post进入(我需要同步/内联响应)

2)我处理请求,并返回一个响应(全XML)

3)如果我在15秒内没有准备好结果,我用"服务器忙,稍后再试"类型的消息响应。

作为中央消息处理机制,我使用了基于任务的方法来排队、启动和等待消息(最多15秒)

当消息几乎是即时处理时,吞吐量(每秒请求数)相当不错(1000/s)。然而,当消息处理延迟200ms时,这将严重降低到40/s

几个片段:

<>之前AddMessage(){Task.Factory.StartNew (() =>{返回worker.ProcessMessage ();};}public messagerresponse (){task.Task。等待(15 * 1000);开关(task.Status){TaskStatus。运行:message = "您的请求花费的时间比平常长"打破;TaskStatus。RanToCompletion:message = (messagerresponse)task.Result;打破;}返回消息;}之前

注意:

任务创建选项无/Longrunning/PreferFairness无影响。当运行visual studio性能分析器时,我可以直观地看到Longrunning为每个请求(预期的)创建一个新线程,而None使用有限的数量(底层线程池)来服务请求。

查看ANTS性能分析器和Visual studio性能分析器,没有争用的并发性问题,也没有其他明显浪费时间的地方(cpu时间或时钟时间)

从可视化结果中可以清楚地看出,在假设有1000个请求排队的情况下,90%的程序时间花在线程服务和上下文切换上

(显然非常昂贵)。我的结论是等待结果(在多个请求中)是非常昂贵的。

如果我在网页或WPF表单上这样做,我可以使它完全异步,但是我没有这个选项。

是否有任何地方我可以改变消息处理机制,以更好地优化并发?我对任何方法都持开放态度,如果有好处的话,我甚至会探索async/await。

提前感谢:)

我猜您看到的性能下降是由于每个请求使用两个线程。

既然你提到你对async/await持开放态度,我会尝试这样做:

public async Task<MessageResponse> GetResult(Message message)
{
  var cts = new CancellationTokenSource(TimeSpan.FromSeconds(15));
  try
  {
    return await Task.Run(() => worker.ProcessMessage(message, cts.Token));
  }
  catch (OperationCanceledException)
  {
    return "Your request is taking longer than usual";
  }
}

您还必须修改ProcessMessage以定期调用CancellationToken.ThrowIfCancellationRequested。另外,如果您的消息处理是I/o绑定的,而不是cpu绑定的,则应该将ProcessMessage更改为async

最新更新