超狂.超提升ASP.NET Web API效能的8種方法(有沒有100倍呀?)
看到一篇 8 ways to improve ASP.NET Web API performance 覺得整理的不錯,順手簡單整理與寫點心得。
- 使用最快的 JSON 序列化套件
ASP.NET Web API 預設採用 JSON.NET。JSON.NET 求穩不求快,如果要求快,透過 ASP.NET Web API 優秀擴充點機制,可隨時更換序列化套件。
之前在 Blog 介紹過 Jil:
- JSON(反)序列化之唯快不破新選擇-Jil
- ASP.NET MVC-取代JsonResult新選擇-招喚JilResult
- ASP.NET Web API-取代JsonFormatter新選擇-招喚JilFormatter
8 Ways作者則是採用 ServiceStack.Text 套件。
圖片來源:theburningmonk.com
- 從 DataReader 手動進行 JSON 序列化
從 DataReader 去建立 JSON 字串能避免不必要的物件創建,這樣不必在從 DataReader 取值與寫入物件,再從物件中取值在PC使用 JSON Serializer 來產生 JSON 物件。你可以從 JSON Serialization of a DataReader 一文得到詳細的說明。
基本上就是使用 StringBuider 來建立 JSON,最後在使用 StringContent 來作為 ASP.NET Web API 回應內容,例如:
var response = Request.CreateResponse(HttpStatusCode.OK);
// jsonResult 為 StringBuider 建立的 JSON
response.Content = new StringContent(jsonResult, Encoding.UTF8, "application/json");
return response;
這一點我採保留,我個人是建議採用第6點裡的建議,除非真的非用 ADO.NET 不可。
- 使用其他協定格式(可能的話)
JSON 的好處是通用性,但在效能議題上就碰到與 JSON.NET 一樣的問題,它能只說是中規中舉。如果要得到高效能的好處,那麼可能要改用更高效的訊息格式(Message Formatter)。例如:Protocol Buffers 或 message pack。
- 實現 GZip 或 Deflate 壓縮
在 ASP.NET Web API 使用 GZip 或 Deflate,對於減少請求與回應封包大小與整理回應速度,是一種投資小量 CPU 能得不少效能提升的手法。
實作方式可以參考我的 Blog 文件:
- 使用快取(Caching)
ASP.NET Web API 的快取和一般的 Web 不同,Web API 走的是更完整的 HTTP 協定,一樣能區分用戶端快取與伺服器端快取。以用戶端快取來看,Web 可能會採用 Cookie、Local Storage、Session Storage 等方法,但 Web API 則是採用 HTTP Header 來控制。
如果你本身並無 Redis 等其他快取設計,我在 ASP.NET Web API 的快取是採用 filipw 設計的套件:Strathweb.CacheOutput。
另外還有一套 CacheCow 也有人介紹。
- 使用傳統 ADO.NET(如果可能)
如果效能對你非常重點,文章作者建立放棄 ORM 回到 ADO.NET 的世界。
我認為這有點矯枉過正,像 Entity Framework 其實執行到最後底層還是 ADO.NET,被包裝過的 ORM 怎麼樣都不可能比原生 ADO.NET 快,但 ORM 帶來的強型別的效益還是很重要的。這兩者之間我們選擇 Dapper 來做為平衡點。
- 在 ASP.NET Web API 採用非同步方法
由於 ASP.NET Web API 是一個 REST/HTTP 服務架構,本身特性非常合適採用非同步來執行。比較新版的 .NET Framework (印象中 4.5 之後)提供大量的 *Async() 尾綴的方法。用戶端也建議使用新改寫的 HttpClient 來請求 Web API 服務。
[HttpGet]
public async Task GetOperationAsync()
{
await Task.Delay(2000);
}
- 回傳多個結果集和集合組合
減少查詢與回應數量,對於用戶端、資料庫和 ASP.NET Web API 三方都有益處。例如,透過 DataModel
來封裝多個物件:
public class AggregateResult
{
public long MaxId { get; set; }
public List<Folder> Folders{ get; set; }
public List<User> Users{ get; set; }
}
我在「twMVC#22 | 一個微信專案從0到.000的效能調教之路」還提到其他許多非程式面的內容,各位也可以參考:
+1
回覆刪除