簡體   English   中英

ASP.NET Web API 2具有Task.Run性能的異步操作方法

[英]ASP.NET Web API 2 Async action methods with Task.Run performance

我正在嘗試使用幾個ASP.NET Web API 2.0端點進行基准測試(使用Apache工作台)。 其中一個是同步和一個異步。

        [Route("user/{userId}/feeds")]
        [HttpGet]
        public IEnumerable<NewsFeedItem> GetNewsFeedItemsForUser(string userId)
        {
            return _newsFeedService.GetNewsFeedItemsForUser(userId);
        }

        [Route("user/{userId}/feeds/async")]
        [HttpGet]
        public async Task<IEnumerable<NewsFeedItem>> GetNewsFeedItemsForUserAsync(string userId)
        {
            return await Task.Run(() => _newsFeedService.GetNewsFeedItemsForUser(userId));
        }

在觀看史蒂夫桑德森的演講之后,我向每個端點發出了以下命令ab -n 100 -c 10 http://localhost....

我很驚訝,因為每個端點的基准似乎大致相同。

關閉史蒂夫解釋說我期待異步端點更高效,因為它會立即將線程池線程釋放回線程池,從而使它們可用於其他請求並提高吞吐量。 但數字看起來完全一樣。

我在這里誤解了什么?

使用await Task.Run創建“異步” WebApi是一個壞主意 - 你仍然會使用一個線程,甚至來自用於請求的同一個線程池

這將導致一些不愉快的時刻在這里詳細描述:

  • 額外(不必要的)線程切換到Task.Run線程池線程。 類似地,當該線程完成請求時,它必須輸入請求上下文(這不是實際的線程切換但確實有開銷)。
  • 創建額外(不必要的)垃圾。 異步編程是一種權衡:以更高的內存使用量為代價,您可以提高響應速度。 在這種情況下,您最終會為完全不必要的異步操作創建更多垃圾。
  • Task.Run“意外地”借用線程池線程拋出ASP.NET線程池啟發式。 我在這里沒有很多經驗,但我的直覺告訴我,如果意外任務真的很短,那么啟發式應該可以很好地恢復,並且如果意外任務持續超過兩秒,則不能優雅地處理它。
  • ASP.NET無法提前終止請求,即,如果客戶端斷開連接或請求超時。 在同步的情況下,ASP.NET知道請求線程並可以中止它。 在異步情況下,ASP.NET不知道輔助線程池線程是“for”該請求。 可以通過使用取消令牌來解決此問題,但這不在本博文的范圍內。

基本上,您不允許任何與ASP.NET的異步 - 您只需隱藏異步外觀后面的CPU綁定同步代碼。 Async本身是I / O綁定代碼的理想選擇,因為它允許以最高效率利用CPU(線程)(不阻塞I / O),但是當你有Compute綁定代碼時,你仍然必須利用它CPU程度相同。

考慮到Task和上下文切換的額外開銷,您將獲得比使用簡單同步控制器方法更糟糕的結果。

如何使其成為真正的ASYNC:

GetNewsFeedItemsForUser方法應該變成async

    [Route("user/{userId}/feeds/async")]
    [HttpGet]
    public async Task<IEnumerable<NewsFeedItem>> GetNewsFeedItemsForUserAsync(string userId)
    {
        return await _newsFeedService.GetNewsFeedItemsForUser(userId);
    }

去做吧:

  • 如果它是一些庫方法,那么尋找它的async變體(如果沒有 - 運氣不好,你將不得不搜索一些競爭模擬)。
  • 如果它是使用文件系統或數據庫的自定義方法,則利用其異步工具為該方法創建異步API。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM