2016-11-10 65 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); 
    ... 
}