1

我有一个困扰我一段时间的性能优化问题。我试图从中获得更多性能,但没有取得多大成功。

系统(简化)如下:

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

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

3) 如果我在 15 秒内没有准备好结果,我会回复“服务器忙,稍后再试”类型的消息。

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

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

几个片段:

    公共无效 AddMessage()
    {
         Task.Factory.StartNew(() =>
                    {
                        返回 worker.ProcessMessage();
                    };
    }

    公共消息响应 GetResult()
            {
                task.Task.Wait(15 * 1000);

                开关(任务.状态)
                {
                    案例TaskStatus.Running:
                            message = "您的请求比平时花费的时间更长"
                       休息;
                    案例TaskStatus.RanToCompletion:
                            message = (MessageResponse)task.Result;
                        休息;
                }
       返回消息;
    }


笔记:

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

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

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

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

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

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

提前致谢 :)

4

1 回答 1

3

我猜您会看到由于每个请求使用两个线程而导致性能下降。

既然你提到你对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 密集型,您应该更改ProcessMessageasync.

于 2013-03-28T15:36:22.983 回答