關於AysncController的一次測試(url重寫後靜態頁文件內容的讀取是否須要使用異步?)

由於作網站的靜態頁緩存,因此作了這個測試html

MVC項目

準備了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()));
    }
}

測試結果

運行環境: 筆記本電腦本地測試。
執行結果:緩存

  1. count = 20




    服務器

  2. count = 100




    網絡

  3. count = 200




    併發

  4. 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()));
     }





  1. count = 1000




    異步

  2. count = 1500

    async

總結

按照過去看過的資料描述 ,應該是 AsyncController雖然會由於線程切換而使單個請求增長額外的處理時間,但使耗時的操做再也不佔用工做線程,從而可讓IIS在相同時間內能夠響應更多的請求,提升吞吐率。ide

第二組Action(延時2秒)的測試結果數據確實反映了這一效果。

但第一組讀取本地文件的測試結果則是 單個請求的處理時間,異步Action明顯高於同步不說,處理相同請求數所消耗的時間也是異步高於同步……,磁盤文件的併發讀取是否是有什麼限制呢?,待確認。

UrlRewrite

  1. 在已經完成MapHandler後就不能重寫了,因此通常在BeginRequest的時候,執行重寫
  2. IIS的url不區分大小寫
  3. ///////home//////index//////////////////,request.Url.PathAndQuery依然是/home/index/
  4. /index.html/ 末尾帶斜槓訪問一個動態頁能夠正常訪問(樣式可能會亂掉),但訪問一個靜態頁會報404

補充測試

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();
                    }
                }
            }
        }
    }
  1. count = 20

  2. count = 100

  3. count = 1000

另外一臺電腦上的測試(Cpu A8)

  1. count = 20
  2. count = 500

測試 服務器?

  1. count = 20

由於用的是360導航的首頁另存爲獲得的一個靜態頁,內容太多,當經過網絡訪問頁面時,帶寬和流量就成爲了一個很大的制約因素,以後更換了一個大小適當的頁面後速度有明顯提高,不過直接訪問靜態頁路徑速度並無明顯提高了……。

相關文章
相關標籤/搜索