提升parralel消息传递性能(TPL / Async)

时间:2013-03-28 15:12:08

标签: c# performance optimization task

我的性能优化问题一直困扰着我。我试图从中获得更多的表现而没有太大的成功。

系统(简化)如下:

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

2)我处理请求,并返回响应(所有XML)

3)如果我在15秒内没有准备好结果,我会在服务器忙碌时回复,稍后再尝试'输入消息。

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

当消息几乎立即处理时,吞吐量(每秒请求数)非常好(1000 / s)。但是,当消息处理延迟200ms时,这会严重降低到40 / s

一些片段:


    public void AddMessage()
    {
         Task.Factory.StartNew(() =>
                    {
                        return worker.ProcessMessage();
                    };
    }

    public MessageResponse GetResult()
            {
                task.Task.Wait(15 * 1000);

                switch (task.Status)
                {
                    case TaskStatus.Running:
                            message = "Your request is taking longer than usual"
                       break;
                    case TaskStatus.RanToCompletion:
                            message = (MessageResponse)task.Result;
                        break;
                }
       return message;
    }


注意:

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

同时看看ANTS性能分析器和Visual Studio性能分析器,争用时没有并发问题,没有其他明显浪费时间的区域(cpu时间或挂钟时间)

可视化结果清楚的是,在1000个请求排队的情况下,90%的程序时间用于线程服务和上下文切换

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

如果我在网页或WPF表单上执行此操作,我可以将其完全异步,但是我没有这个选项。

有什么地方可以改变消息处理机制来更好地优化并发性吗?我对任何事情都持开放态度,甚至可以探索async / await,如果它会受益。

提前致谢:)

1 个答案:

答案 0 :(得分:2)

我猜你会因为每个请求使用两个线程而导致性能下降。

既然你提到你对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