基准测试ASP.NET并发请求效果不佳

rea*_*Pro 11 asp.net iis asp.net-web-api

我有以下代码,我使用jMeter进行基准测试,并在我的localhost机器上每秒获得大约3000个请求(await故意无意地同步运行):

public async Task<HttpResponseMessage> Get()
{
    var resp = new HttpResponseMessage(HttpStatusCode.OK);
    resp.Content = new StringContent(Thread.CurrentThread.ManagedThreadId.ToString(), Encoding.UTF8, "text/plain");
    return resp;
}
Run Code Online (Sandbox Code Playgroud)

问题是,当我暂停请求一秒钟时,如下所示,由于某种原因,每个w3wp.exe进程的吞吐量降至每秒10个请求(同样await有意无意地同步运行):

public async Task<HttpResponseMessage> Get()
    {
        Task.Delay(1000).Wait();
        var resp = new HttpResponseMessage(HttpStatusCode.OK);
        resp.Content = new StringContent(Thread.CurrentThread.ManagedThreadId.ToString(), Encoding.UTF8, "text/plain");
        return resp;
    }
Run Code Online (Sandbox Code Playgroud)

即使我使用await它也没有区别,每秒10个请求根本没有改进:

public async Task<HttpResponseMessage> Get()
{
    await Task.Delay(1000);
    var resp = new HttpResponseMessage(HttpStatusCode.OK);
    resp.Content = new StringContent(Thread.CurrentThread.ManagedThreadId.ToString(), Encoding.UTF8, "text/plain");
    return resp;
}
Run Code Online (Sandbox Code Playgroud)

我尝试了所有配置设置,没有任何改变:`

web.config中

  <system.net>
    <connectionManagement>
      <add address="*" maxconnection="65400" />
    </connectionManagement>
  </system.net>
Run Code Online (Sandbox Code Playgroud)

aspnet.config

  <system.web>
    <applicationPool 
        maxConcurrentThreadsPerCPU="100" />
  </system.web>
Run Code Online (Sandbox Code Playgroud)

machine.config中

 <processModel
 autoConfig="false"
 memoryLimit="70"
 maxWorkerThreads="100"
 maxIoThreads="100" />
Run Code Online (Sandbox Code Playgroud)

配置为x86和x64

我有32个内存和4个物理内核,Windows 10.

当每秒调整10个请求时,CPU不会超过10%的负载.

上面的代码使用WEB API,但我当然使用HTTP Handler重现相同的结果.

Ste*_*per 2

这是一个可能的理解。无论如何,这是一个要调查的人。

Task.Delay() 创建一个新任务,其任务是暂停。如果我理解正确的话,任务通常会被分派到 .Net 工作池,该池的大小有限。(您可以使用ThreadPool.GetMaxThreads检查)当您尝试放入太多线程时,代码将“备份”,因为它等待线程池有空间。

假设您有一个大小为 40 的线程池。一旦您分派了 40 个任务,并且全部等待一秒钟,您就耗尽了线程池。你的瓶颈将是任务,堵塞线程池,而不是产生空间。

通常,执行昂贵 IO(例如数据库查询或文件 IO)的任务在等待工作完成时会产生控制。我想知道 Task.Delay 是否更“粘人”。

尝试将 Task.Delay() 替换为 System.Threading.Thread.Sleep() 并查看是否会改变任何内容。