2016-11-10 48 views
0

我收看了这部影片:https://channel9.msdn.com/Events/TechDays/Techdays-2012-the-Netherlands/2287。所以我试图在控制器中实现async/await的使用。所以这是basicaly我所做的:为什么不是异步等待提高性能?

public class HomeController : Controller 
    { 
     private static WebClient _webClient = new WebClient(); 
     public async Task<ActionResult> IndexAsync() 
     { 
      var data = await _webClient.DownloadStringTaskAsync("http://stackoverflow.com/"); 
      return View("Index", (object)data); 
     } 
     public ActionResult Index() 
     { 
      var data = _webClient.DownloadString("http://stackoverflow.com/"); 
      return View("Index", (object)data); 
     } 
    } 

然后我用Apache的基准,并做了以下两个测试:

ab -n 100 -c 100 http://localhost:53446/Home/index 

ab -n 100 -c 100 http://localhost:53446/Home/indexasync 

而且我得到了完全相同的性能(我有8个CPU核心)。这是为什么 ?

+1

是你期待什么样的性能改进? – trashr0x

+2

您没有多个同时运行的异步操作,所以我预计不会有任何加速。 – Amy

+2

对于单个请求,您更有可能在性能上看到* drop *。异步通过允许处理更多*并发*请求来减轻负载。 –

回答

3

有几个原因突出。

Using Asynchronous Methods in ASP.NET MVC 4

线程池中的线程数是有限的(默认最大为.NET 4.5是5000)。在长时间运行请求的高并发性的大型应用程序中,所有可用的线程可能都很忙。这种情况被称为线程匮乏。

因此,一次运行100个请求甚至不会开始让您的线程饿死。

另外,一个简单的GET请求会很快运行。执行需要几秒甚至几分钟的动作的测试会带来更明显的性能提升。

+0

该限制是非常高的,但据我所知,这些5000线程默认情况下并未添加到池中。当您询问更多时会添加线程,这会导致请求排队。 –

+0

我刚刚尝试使用大文件(42mb),并且在异步和同步中仍然获得相同的结果。 –

+0

对于可伸缩性和内存,这些改进会比执行速度更快。内存占用是否在两者之间发生变化?如果将请求数量增加到1000或更多,会怎么样?本文很好地解释async/await如何减少内存使用量:https://msdn.microsoft.com/en-us/magazine/dn802603.aspx – davidmdem

7

异步是而不是关于性能。这只是绝对不正确的。事实上,异步请求通常会少于的同步性能,只是因为异步需要额外的开销。

使用异步的原因是关于高效的资源管理和规模。典型的Web服务器进程将有大约1000个线程。这通常被称为“最大请求”,因为一个线程通常等于一个请求。如果你有一个8核心的CPU,理想的情况是每个核心都有一个进程(在IIS中称为“网络工作者”)。所以,从理论上讲,你总共需要约8000个线程。

这实际上相当多,尽管现代网页比大多数人想象的消耗更多的请求。该页面本身就是一个请求,但该页面将包含图像和外部JS和CSS文件,所有这些文件都会生成请求,并且通常会使用AJAX进行进一步请求。关键是,虽然8000+线程仍然是你的池中的很多,但如果服务器负载很重,仍然可能会耗尽。

异步仅为您提供高于此限制的呼吸空间。在线程进入等待状态的情况下,可以将其返回到池以便在完成任何外部操作时发出其他请求。另一种方法是线程只是在那里闲置(同步)。这就是它的全部。这完全是为了处理那些空闲的线程和其他一些工作,这可能意味着请求排队,超时或正在处理的请求之间的差异,即使是缓慢的。

+0

我同意你的看法,但默认情况下,Asp.Net MVC保留8个线程(https://msdn.microsoft.com/en-us/library/system.threading.threadpool.setminthreads(v=vs.110).aspx) ,所以在第8次请求之后,我的第9和第10次应该会比较慢,因为在创建新的之前,asp.net会等待Xms(我认为它是500,但不确定)。 –

+0

你在这里的假设是不正确的。在启动线程时有一些开销,所以这个设置是作为一种前置加载的方式存在的。但是,线程是否存在或创建并不是*真正的问题,关于同步和异步之间的区别肯定无关紧要,因为这必然会发生。只有当所有可用的线程都在使用时,才会看到同步和异步之间的任何差异,而不管它们是如何或何时创建的。 –

+0

我仍然不明白channel9视频的性能如何提升。感谢您的时间 –

2

运行一个耗尽线程池的负载测试很难在本地机器上执行。它更容易很多假装线程池被人为地限制其耗尽,因为我做的in my gist

protected void Application_Start() 
{ 
    int workerThreads, ioThreads; 
    ThreadPool.GetMaxThreads(out workerThreads, out ioThreads); 
    ThreadPool.SetMaxThreads(Environment.ProcessorCount, ioThreads); 
    ... 
}