由於作網站的靜態頁緩存,因此作了這個測試html
準備了4個Action,分兩組,一組是讀取本地磁盤的一個html頁面文件,一組是延時2秒c#
public class TestController : Controller { public ActionResult Article(string name) { string path = @"I:\c#\nn.html"; using (StreamReader reader = new StreamReader(path)) { return Content(reader.ReadToEnd()); } } public async Task<ActionResult> Article2(string name) { string path = @"I:\c#\nn.html"; using (StreamReader reader = new StreamReader(path)) { return Content(await reader.ReadToEndAsync()); } } public ActionResult Index1() { Thread.Sleep(2000); return Content("synchronized"); } public async Task<ActionResult> Index2() { await Task.Delay(2000); return Content("asynchronized"); } }
class Program { static void Main(string[] args) { var syncUrl = "http://localhost:61771/Test/Article"; var asyncUrl = "http://localhost:61771/Test/Article2"; var syncUrl2 = "http://localhost:61771/Test/Index1"; var asyncUrl2 = "http://localhost:61771/Test/Index2"; var count = 20; int i = 0; while (true) { Console.WriteLine(); Benchmark(asyncUrl, count); Benchmark(syncUrl, count); Benchmark(asyncUrl2, count); Benchmark(syncUrl2, count); i++; if (Console.ReadKey().Key == ConsoleKey.C) { break; } } Console.ReadKey(); } static void Benchmark(string url, int count) { var stopwatch = new Stopwatch(); stopwatch.Start(); var threads = new List<Thread>(); var countdown = new CountdownEvent(count); for (int i = 0; i < count; i++) { threads.Add(new Thread(() => { using (var client = new WebClient()) { client.DownloadData(url); countdown.Signal(); } })); } for (int i = 0; i < count; i++) { threads[i].Start(); } while (!countdown.IsSet) ; stopwatch.Stop(); Console.WriteLine(string.Format("{0} costs {1} ms", url, stopwatch.ElapsedMilliseconds.ToString())); } }
運行環境: 筆記本電腦本地測試。
執行結果:緩存
count = 20
服務器
count = 100
網絡
count = 200
併發
count = 500
測試時WebClient拋出了請求超時的警告,
代碼調整以下:mvc
public class NewWebClient : WebClient { private int _timeout; public NewWebClient() { this._timeout = 60000; } public NewWebClient(int timeout) { this._timeout = timeout; } protected override WebRequest GetWebRequest(Uri address) { var result = base.GetWebRequest(address); result.Timeout = this._timeout; return result; } } static void Benchmark(string url, int count) { var stopwatch = new Stopwatch(); stopwatch.Start(); var threads = new List<Thread>(); var countdown = new CountdownEvent(count); for (int i = 0; i < count; i++) { threads.Add(new Thread(() => { using (var client = new NewWebClient(30 * 60 * 1000)) { client.DownloadData(url); countdown.Signal(); } })); } for (int i = 0; i < count; i++) { threads[i].Start(); } while (!countdown.IsSet) ; stopwatch.Stop(); Console.WriteLine(string.Format("{0} costs {1} ms", url, stopwatch.ElapsedMilliseconds.ToString())); }
count = 1000
異步
count = 1500
async
按照過去看過的資料描述 ,應該是 AsyncController雖然會由於線程切換而使單個請求增長額外的處理時間,但使耗時的操做再也不佔用工做線程,從而可讓IIS在相同時間內能夠響應更多的請求,提升吞吐率。ide
第二組Action(延時2秒)的測試結果數據確實反映了這一效果。
但第一組讀取本地文件的測試結果則是 單個請求的處理時間,異步Action明顯高於同步不說,處理相同請求數所消耗的時間也是異步高於同步……,磁盤文件的併發讀取是否是有什麼限制呢?,待確認。
protected void Application_BeginRequest() { var context = HttpContext.Current; var request = context.Request; if (request.RequestType == "GET")//過濾全部API { string regularUrl = request.Url.PathAndQuery; if (regularUrl.StartsWith("/Test/Article3")) { context.RewritePath("/Project_Readme.html"); } else if (regularUrl.StartsWith("/Test/Article4")) { string path = context.Server.MapPath("~/Project_Readme.html"); if (File.Exists(path)) { using (StreamReader reader = new StreamReader(path)) { context.Response.Write( reader.ReadToEnd()); context.Response.End(); } } } } }
count = 20
count = 100
count = 1000
另外一臺電腦上的測試(Cpu A8)
測試 服務器?
由於用的是360導航的首頁另存爲獲得的一個靜態頁,內容太多,當經過網絡訪問頁面時,帶寬和流量就成爲了一個很大的制約因素,以後更換了一個大小適當的頁面後速度有明顯提高,不過直接訪問靜態頁路徑速度並無明顯提高了……。