亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ASP.NET頁面優化的方法

發布時間:2021-10-29 11:02:47 來源:億速云 閱讀:139 作者:柒染 欄目:編程語言

這篇文章將為大家詳細講解有關ASP.NET頁面優化的方法,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

今天與大家分享:一種優化頁面執行速度的方法。

采用這個方法,可以使用頁面的執行速度獲得【8倍】的提升效果。

為了讓您對優化的效果有個直觀的了解,我準備了下面的測試結果截圖:

ASP.NET頁面優化的方法

測試環境:

  1. Windows Server 2003 SP2

  2. Viaual Studio 2008,使用自帶的WebDev.WebServer.EXE運行網站程序。

  3. (ThinkPad SL510):Core2 T6670 2.2GHz, 4G內存

二個紅框中的數字反映了優化前后的執行時間。

數字表明:優化前后,執行時間有了8倍多的差別。

本文的測試結果也僅僅只是一個參考數字,這個結果也只是根據我所設計的測試頁面得出的。

優化的過程中,如果不使用服務器控件,那么給GC減少的壓力其實也是無法測試到的。

在測試過程中,我還發現測試結果并不是很穩定,因此截圖具有一定的偶然性。

測試頁面或許在某些方面存在一些片面性,因此,結果僅供參考。

ASP.NET頁面優化的方法

測試背景

看過了優化結果,再來介紹一下:這個測試到底是在測試什么東西?

現在有很多做ASP.NET的開發人員,應該都是從ASP.NET的WebForm編程模型開始學習的。大家都很喜歡用服務器控件,不管輸出什么,都會使用服務器控件。有時候為了讓頁面呈現干凈的HTML代碼,有些人會選擇使用Repeater,Literal這類簡單的服務器控件。或許有些人認為:我已不使用GridView這樣強大復雜的控件,頁面執行速度已經很快了。

真是這樣嗎?

今天測試的起點就從使用簡單的服務器開始,我會分二次對它做一系列的性能優化。

最終就是上圖中的3個結果,它們反映了二次優化的改進過程。

在繼續介紹之前,有一點我想有必要說明一下:

優化的過程涉及到ASP.NET服務器控件的使用,測試結果也僅僅只是一個參考數字。

如果您認為您的開發工作非常依賴于服務器控件的使用,

那么測試結果對您來說其實是無意義的,請不要在意這個結果。

ASP.NET頁面優化的方法

測試方法

在這次優化過程中,我并沒有設計很復雜的測試頁面,而是一個很簡單的測試頁面,頁面顯示效果如下:

ASP.NET頁面優化的方法

這個頁面其實就是顯示了一堆超鏈接,它們來自于我的博客側邊欄的【推薦排行榜】,總共有20條記錄,我讓頁面重復5次輸出,也就是生成了100個超鏈接。

測試的數據是這樣獲取的:

我復制了我的博客側邊欄的【推薦排行榜】的那段HTML代碼,保存到一個文件中:

ASP.NET頁面優化的方法

然后,網站在初始化時,從這段HTML代碼提取鏈接地址以及顯示文字,保存到一個BlogInfo的列表中,代碼如下:

public class BlogInfo  {      public string Title;      public string Href;  }   public static class XmlDb  {      public static List<BlogInfo> Blogs { get; private set; }        public static void LoadBlogs()      {          string filePath = Path.Combine(HttpRuntime.AppDomainAppPath, @"App_Data\RecommendList.html");           XElement html = XElement.Parse(System.IO.File.ReadAllText(filePath));           Blogs =              (from a in html.Elements("li").Elements("a")               select new BlogInfo { Title = a.Value, Href = a.Attribute("href").Value }).ToList();      }  }

測試時,就把XmlDb.Blogs的內容顯示在網頁中。
我想這個測試還是比較接近于現實開發的。

這里又有一個問題:我如何測試頁面的執行速度?

雖然說創建HttpWebRequest訪問頁面是個很簡單的方法,但我并不打算這樣做。
因為從HttpWebRequest發起調用到獲取結果,這其中除了有頁面的執行時間,還混雜較多的額外調用開銷。最終,我選擇了在一次HTTP請求中,循環調用Server.Execute來執行頁面,并統計時間的方式。其實如何選擇測試方法,對于二個測試對象還說,都是公平的。只是說:盡量減少一些額外的調用開銷,會讓測試結果的差異更大,也更明顯。

說明:為了測試代碼寫起來簡單,我使用了MyMVC框架。

ASP.NET頁面優化的方法

測試用例1:WebFromPage.aspx

前面介紹了測試背景以及測試方法。現在就來介紹第1個測試用例,它采用了WebForm編程模型中最經典的寫法。

頁面代碼:

<%@ Page Language="C#" CodeFile="WebFromPage.aspx.cs" Inherits="TestPage_WebFromPage" %>  <html xmlns="http://www.w3.org/1999/xhtml"> <head>     <title>PagePerformanceTest   http://www.cnblogs.com/fish-li/</title> </head> <body>  <p>This is WebFromPage.aspx</p>  <asp:Repeater ID="repeater1" runat="server" onitemdatabound="repeater1_ItemDataBound"> <ItemTemplate>     <asp:HyperLink ID="link1" runat="server"></asp:HyperLink><br /> </ItemTemplate> <FooterTemplate><hr /></FooterTemplate> </asp:Repeater>  <asp:Repeater ID="repeater2" runat="server" onitemdatabound="repeater1_ItemDataBound"> <ItemTemplate>     <asp:HyperLink ID="link1" runat="server"></asp:HyperLink><br /> </ItemTemplate> <FooterTemplate><hr /></FooterTemplate> </asp:Repeater>  <asp:Repeater ID="repeater3" runat="server" onitemdatabound="repeater1_ItemDataBound"> <ItemTemplate>     <asp:HyperLink ID="link1" runat="server"></asp:HyperLink><br /> </ItemTemplate> <FooterTemplate><hr /></FooterTemplate> </asp:Repeater>  <asp:Repeater ID="repeater4" runat="server" onitemdatabound="repeater1_ItemDataBound"> <ItemTemplate>     <asp:HyperLink ID="link1" runat="server"></asp:HyperLink><br /> </ItemTemplate> <FooterTemplate><hr /></FooterTemplate> </asp:Repeater>  <asp:Repeater ID="repeater5" runat="server" onitemdatabound="repeater1_ItemDataBound"> <ItemTemplate>     <asp:HyperLink ID="link1" runat="server"></asp:HyperLink><br /> </ItemTemplate> <FooterTemplate><hr /></FooterTemplate> </asp:Repeater>   </body> </html>

頁面的CodeFile代碼:

public partial class TestPage_WebFromPage : System.Web.UI.Page  {      protected override void OnLoad(EventArgs e)      {          base.OnLoad(e);           repeater1.DataSource = XmlDb.Blogs;          repeater1.DataBind();          repeater2.DataSource = XmlDb.Blogs;          repeater2.DataBind();          repeater3.DataSource = XmlDb.Blogs;          repeater3.DataBind();          repeater4.DataSource = XmlDb.Blogs;          repeater4.DataBind();          repeater5.DataSource = XmlDb.Blogs;          repeater5.DataBind();      }       protected void repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)      {          if( e.Item.ItemType == ListItemType.Item ) {              BlogInfo blog = e.Item.DataItem as BlogInfo;              HyperLink link1 = e.Item.FindControl("link1") as HyperLink;              link1.NavigateUrl = blog.Href;              link1.Text = blog.Title;          }      }  }

測試代碼:

[Action]  public object Test1(string callTimes)  {      int count = 0;      int.TryParse(callTimes, out count);      if( count <= 0 )          return count;       HttpContext context = HttpContext.Current;            // 先執行一次,排除編譯時間      string html = MyMVC.PageExecutor.Render(context, "/TestPage/WebFromPage.aspx", null);       Stopwatch watch = Stopwatch.StartNew();      for( int i = 0; i < count; i++ )          html = MyMVC.PageExecutor.Render(context, "/TestPage/WebFromPage.aspx", null);      watch.Stop();       return watch.Elapsed.ToString();  }

當我測試執行10000次時,耗時:00:00:07.5607229

ASP.NET頁面優化的方法

測試用例2:InlinePage.aspx

與測試用例1不同,測試用例2則完全不使用服務器控件。

頁面代碼:

<%@ Page Language="C#" %>  <html xmlns="http://www.w3.org/1999/xhtml"> <head>     <title>PagePerformanceTest   http://www.cnblogs.com/fish-li/</title> </head> <body>  <p>This is InlinePage.aspx</p>  <% foreach( BlogInfo b in XmlDb.Blogs ) { %>     <a href="<%= b.Href %>" target="_blank"><%= b.Title %></a><br /> <% } %> <hr />  <% foreach( BlogInfo b in XmlDb.Blogs ) { %>     <a href="<%= b.Href %>" target="_blank"><%= b.Title %></a><br /> <% } %> <hr />  <% foreach( BlogInfo b in XmlDb.Blogs ) { %>     <a href="<%= b.Href %>" target="_blank"><%= b.Title %></a><br /> <% } %> <hr />  <% foreach( BlogInfo b in XmlDb.Blogs ) { %>     <a href="<%= b.Href %>" target="_blank"><%= b.Title %></a><br /> <% } %> <hr />  <% foreach( BlogInfo b in XmlDb.Blogs ) { %>     <a href="<%= b.Href %>" target="_blank"><%= b.Title %></a><br /> <% } %> <hr />  </body> </html>

測試代碼:

[Action]  public object Test2(string callTimes)  {      int count = 0;      int.TryParse(callTimes, out count);      if( count <= 0 )          return count;       HttpContext context = HttpContext.Current;       // 先執行一次,排除編譯時間      string html = MyMVC.PageExecutor.Render(context, "/TestPage/InlinePage.aspx", null);       Stopwatch watch = Stopwatch.StartNew();      for( int i = 0; i < count; i++ )          html = MyMVC.PageExecutor.Render(context, "/TestPage/InlinePage.aspx", null);      watch.Stop();       return watch.Elapsed.ToString();  }

當我測試執行10000次時,耗時:00:00:01.2345842

ASP.NET頁面優化的方法

分析優化結果1

測試用例1執行相同次數所花費的時間是測試用例2的6倍,為什么會這樣呢?

為了回答這個問題,我們首先要知道前面二個頁面在執行時,它們是如何運行的。

說到這里,就不得不談ASP.NET的頁面編譯方式了。

ASP.NET的頁面編譯過程是個復雜的操作,其實我們可以不用關心頁面是如何編譯的,但要知道:頁面編譯后是什么樣的。

為了能直觀地了解頁面編譯后的樣子,我編譯了整個網站,并生成到一個DLL文件中,然后使用Reflector.exe來分析這個DLL的源代碼。

將網站編譯成一個DLL文件有二個方法:

  1. 安裝WebDeployment插件。

  2. 使用我的工具:FishAspnetTool

本文將使用FishAspnetTool來編譯測試網站獲得編譯后的DLL文件。

FishAspnetTool是什么?

FishAspnetTool是我在使用Visual Web Developer 2005時,為了方便編譯網站而寫的一個小工具。

下載地址:http://www.cnblogs.com/fish-li/archive/2011/10/30/2229497.html

注意:下載的是一個工具包,安裝后,從開始菜單中運行FishTools\FishAspnetTool即可。

下面是工具的運行截圖。

ASP.NET頁面優化的方法

操作方法:

1. 點擊粉色按鈕,選擇網站路徑。

2. 單選按鈕選擇第2項。

3. 點擊【發布網站】按鈕。

在編譯網站之后,我就可以知道網站在運行時如何運行頁面了。

測試用例1的頁面,最后被編譯成這樣了:

namespace ASP  {      using System;      using System.Diagnostics;      using System.Runtime.CompilerServices;      using System.Web;      using System.Web.UI;      using System.Web.UI.WebControls;       [CompilerGlobalScope]      public class testpage_webfrompage_aspx : TestPage_WebFromPage, IHttpHandler      {          private static object __fileDependencies;          private static bool __initialized;           [DebuggerNonUserCode]          public testpage_webfrompage_aspx()          {              base.AppRelativeVirtualPath = "~/TestPage/WebFromPage.aspx";              if (!__initialized)              {                  string[] virtualFileDependencies = new string[] { "~/TestPage/WebFromPage.aspx", "~/TestPage/WebFromPage.aspx.cs" };                  __fileDependencies = base.GetWrappedFileDependencies(virtualFileDependencies);                  __initialized = true;              }              base.Server.ScriptTimeout = 0x1c9c380;          }           [DebuggerNonUserCode]          private void __BuildControl__control10(Control __ctrl)          {              IParserAccessor accessor = __ctrl;              accessor.AddParsedSubObject(new LiteralControl("<hr />"));          }           [DebuggerNonUserCode]          private void __BuildControl__control11(Control __ctrl)          {              IParserAccessor accessor = __ctrl;              accessor.AddParsedSubObject(new LiteralControl("\r\n\t"));              HyperLink link = this.__BuildControl__control12();              accessor.AddParsedSubObject(link);              accessor.AddParsedSubObject(new LiteralControl("<br />\r\n"));          }           [DebuggerNonUserCode]          private HyperLink __BuildControl__control12()          {              HyperLink link = new HyperLink {                  TemplateControl = this             };              link.ApplyStyleSheetSkin(this);              link.ID = "link1";              return link;          }           [DebuggerNonUserCode]          private void __BuildControl__control13(Control __ctrl)          {              IParserAccessor accessor = __ctrl;              accessor.AddParsedSubObject(new LiteralControl("<hr />"));          }           [DebuggerNonUserCode]          private void __BuildControl__control14(Control __ctrl)          {              IParserAccessor accessor = __ctrl;              accessor.AddParsedSubObject(new LiteralControl("\r\n\t"));              HyperLink link = this.__BuildControl__control15();              accessor.AddParsedSubObject(link);              accessor.AddParsedSubObject(new LiteralControl("<br />\r\n"));          }           [DebuggerNonUserCode]          private HyperLink __BuildControl__control15()          {              HyperLink link = new HyperLink {                  TemplateControl = this             };              link.ApplyStyleSheetSkin(this);              link.ID = "link1";              return link;          }           [DebuggerNonUserCode]          private void __BuildControl__control16(Control __ctrl)          {              IParserAccessor accessor = __ctrl;              accessor.AddParsedSubObject(new LiteralControl("<hr />"));          }           [DebuggerNonUserCode]          private void __BuildControl__control2(Control __ctrl)          {              IParserAccessor accessor = __ctrl;              accessor.AddParsedSubObject(new LiteralControl("\r\n\t"));              HyperLink link = this.__BuildControl__control3();              accessor.AddParsedSubObject(link);              accessor.AddParsedSubObject(new LiteralControl("<br />\r\n"));          }           [DebuggerNonUserCode]          private HyperLink __BuildControl__control3()          {              HyperLink link = new HyperLink {                  TemplateControl = this             };              link.ApplyStyleSheetSkin(this);              link.ID = "link1";              return link;          }           [DebuggerNonUserCode]          private void __BuildControl__control4(Control __ctrl)          {              IParserAccessor accessor = __ctrl;              accessor.AddParsedSubObject(new LiteralControl("<hr />"));          }           [DebuggerNonUserCode]          private void __BuildControl__control5(Control __ctrl)          {              IParserAccessor accessor = __ctrl;              accessor.AddParsedSubObject(new LiteralControl("\r\n\t"));              HyperLink link = this.__BuildControl__control6();              accessor.AddParsedSubObject(link);              accessor.AddParsedSubObject(new LiteralControl("<br />\r\n"));          }           [DebuggerNonUserCode]          private HyperLink __BuildControl__control6()          {              HyperLink link = new HyperLink {                  TemplateControl = this             };              link.ApplyStyleSheetSkin(this);              link.ID = "link1";              return link;          }           [DebuggerNonUserCode]          private void __BuildControl__control7(Control __ctrl)          {              IParserAccessor accessor = __ctrl;              accessor.AddParsedSubObject(new LiteralControl("<hr />"));          }           [DebuggerNonUserCode]          private void __BuildControl__control8(Control __ctrl)          {              IParserAccessor accessor = __ctrl;              accessor.AddParsedSubObject(new LiteralControl("\r\n\t"));              HyperLink link = this.__BuildControl__control9();              accessor.AddParsedSubObject(link);              accessor.AddParsedSubObject(new LiteralControl("<br />\r\n"));          }           [DebuggerNonUserCode]          private HyperLink __BuildControl__control9()          {              HyperLink link = new HyperLink {                  TemplateControl = this             };              link.ApplyStyleSheetSkin(this);              link.ID = "link1";              return link;          }           [DebuggerNonUserCode]          private Repeater __BuildControlrepeater1()          {              Repeater repeater = new Repeater();              base.repeater1 = repeater;              repeater.ItemTemplate = new CompiledTemplateBuilder(new BuildTemplateMethod(this.__BuildControl__control2));              repeater.FooterTemplate = new CompiledTemplateBuilder(new BuildTemplateMethod(this.__BuildControl__control4));              repeater.ID = "repeater1";              repeater.ItemDataBound += new RepeaterItemEventHandler(this.repeater1_ItemDataBound);              return repeater;          }           [DebuggerNonUserCode]          private Repeater __BuildControlrepeater2()          {              Repeater repeater = new Repeater();              base.repeater2 = repeater;              repeater.ItemTemplate = new CompiledTemplateBuilder(new BuildTemplateMethod(this.__BuildControl__control5));              repeater.FooterTemplate = new CompiledTemplateBuilder(new BuildTemplateMethod(this.__BuildControl__control7));              repeater.ID = "repeater2";              repeater.ItemDataBound += new RepeaterItemEventHandler(this.repeater1_ItemDataBound);              return repeater;          }           [DebuggerNonUserCode]          private Repeater __BuildControlrepeater3()          {              Repeater repeater = new Repeater();              base.repeater3 = repeater;              repeater.ItemTemplate = new CompiledTemplateBuilder(new BuildTemplateMethod(this.__BuildControl__control8));              repeater.FooterTemplate = new CompiledTemplateBuilder(new BuildTemplateMethod(this.__BuildControl__control10));              repeater.ID = "repeater3";              repeater.ItemDataBound += new RepeaterItemEventHandler(this.repeater1_ItemDataBound);              return repeater;          }           [DebuggerNonUserCode]          private Repeater __BuildControlrepeater4()          {              Repeater repeater = new Repeater();              base.repeater4 = repeater;              repeater.ItemTemplate = new CompiledTemplateBuilder(new BuildTemplateMethod(this.__BuildControl__control11));              repeater.FooterTemplate = new CompiledTemplateBuilder(new BuildTemplateMethod(this.__BuildControl__control13));              repeater.ID = "repeater4";              repeater.ItemDataBound += new RepeaterItemEventHandler(this.repeater1_ItemDataBound);              return repeater;          }           [DebuggerNonUserCode]          private Repeater __BuildControlrepeater5()          {              Repeater repeater = new Repeater();              base.repeater5 = repeater;              repeater.ItemTemplate = new CompiledTemplateBuilder(new BuildTemplateMethod(this.__BuildControl__control14));              repeater.FooterTemplate = new CompiledTemplateBuilder(new BuildTemplateMethod(this.__BuildControl__control16));              repeater.ID = "repeater5";              repeater.ItemDataBound += new RepeaterItemEventHandler(this.repeater1_ItemDataBound);              return repeater;          }           [DebuggerNonUserCode]          private void __BuildControlTree(testpage_webfrompage_aspx __ctrl)          {              __ctrl.EnableViewState = false;              __ctrl.EnableViewStateMac = false;              this.InitializeCulture();              IParserAccessor accessor = __ctrl;              accessor.AddParsedSubObject(new LiteralControl("\r\n\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n<head>\r\n    <title>PagePerformanceTest   http://www.cnblogs.com/fish-li/</title>\r\n</head>\r\n<body>\r\n\r\n<p>This is WebFromPage.aspx</p>\r\n\r\n"));              Repeater repeater = this.__BuildControlrepeater1();              accessor.AddParsedSubObject(repeater);              accessor.AddParsedSubObject(new LiteralControl("\r\n\r\n"));              Repeater repeater2 = this.__BuildControlrepeater2();              accessor.AddParsedSubObject(repeater2);              accessor.AddParsedSubObject(new LiteralControl("\r\n\r\n"));              Repeater repeater3 = this.__BuildControlrepeater3();              accessor.AddParsedSubObject(repeater3);              accessor.AddParsedSubObject(new LiteralControl("\r\n\r\n"));              Repeater repeater4 = this.__BuildControlrepeater4();              accessor.AddParsedSubObject(repeater4);              accessor.AddParsedSubObject(new LiteralControl("\r\n\r\n"));              Repeater repeater5 = this.__BuildControlrepeater5();              accessor.AddParsedSubObject(repeater5);              accessor.AddParsedSubObject(new LiteralControl("\r\n\r\n\r\n</body>\r\n</html>\r\n"));          }           [DebuggerNonUserCode]          protected override void FrameworkInitialize()          {              base.FrameworkInitialize();              this.__BuildControlTree(this);              base.AddWrappedFileDependencies(__fileDependencies);              base.Request.ValidateInput();          }           [DebuggerNonUserCode]          public override int GetTypeHashCode()          {              return -781896338;          }           [DebuggerNonUserCode]          public override void ProcessRequest(HttpContext context)          {              base.ProcessRequest(context);          }           protected override bool SupportAutoEvents          {              get              {                  return false;              }          }      }  }

從這個編譯結果我們可以看出:頁面上的所有文字最后也被包裝到LiteralControl中。

頁面中呈現時,就是循環調用每個控件的Render方法來最終生成HTML結果。

測試用例2的頁面被編譯成這個樣了:

namespace ASP  {      using System;      using System.Diagnostics;      using System.Runtime.CompilerServices;      using System.Web;      using System.Web.Profile;      using System.Web.UI;       [CompilerGlobalScope]      public class testpage_inlinepage_aspx : Page, IHttpHandler      {          private static object __fileDependencies;          private static bool __initialized;           [DebuggerNonUserCode]          public testpage_inlinepage_aspx()          {              base.AppRelativeVirtualPath = "~/TestPage/InlinePage.aspx";              if (!__initialized)              {                  string[] virtualFileDependencies = new string[] { "~/TestPage/InlinePage.aspx" };                  __fileDependencies = base.GetWrappedFileDependencies(virtualFileDependencies);                  __initialized = true;              }              base.Server.ScriptTimeout = 0x1c9c380;          }           [DebuggerNonUserCode]          private void __BuildControlTree(testpage_inlinepage_aspx __ctrl)          {              __ctrl.EnableViewState = false;              __ctrl.EnableViewStateMac = false;              this.InitializeCulture();              __ctrl.SetRenderMethodDelegate(new RenderMethod(this.__Render__control1));          }           private void __Render__control1(HtmlTextWriter __w, Control parameterContainer)          {              __w.Write("\r\n\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n<head>\r\n    <title>PagePerformanceTest   http://www.cnblogs.com/fish-li/</title>\r\n</head>\r\n<body>\r\n\r\n<p>This is InlinePage.aspx</p>\r\n\r\n");              foreach (BlogInfo info in XmlDb.Blogs)              {                  __w.Write("\r\n\t<a href=\"");                  __w.Write(info.Href);                  __w.Write("\" target=\"_blank\">");                  __w.Write(info.Title);                  __w.Write("</a><br />\r\n");              }              __w.Write("\r\n<hr />\r\n\r\n");              foreach (BlogInfo info2 in XmlDb.Blogs)              {                  __w.Write("\r\n\t<a href=\"");                  __w.Write(info2.Href);                  __w.Write("\" target=\"_blank\">");                  __w.Write(info2.Title);                  __w.Write("</a><br />\r\n");              }              __w.Write("\r\n<hr />\r\n\r\n");              foreach (BlogInfo info3 in XmlDb.Blogs)              {                  __w.Write("\r\n\t<a href=\"");                  __w.Write(info3.Href);                  __w.Write("\" target=\"_blank\">");                  __w.Write(info3.Title);                  __w.Write("</a><br />\r\n");              }              __w.Write("\r\n<hr />\r\n\r\n");              foreach (BlogInfo info4 in XmlDb.Blogs)              {                  __w.Write("\r\n\t<a href=\"");                  __w.Write(info4.Href);                  __w.Write("\" target=\"_blank\">");                  __w.Write(info4.Title);                  __w.Write("</a><br />\r\n");              }              __w.Write("\r\n<hr />\r\n\r\n");              foreach (BlogInfo info5 in XmlDb.Blogs)              {                  __w.Write("\r\n\t<a href=\"");                  __w.Write(info5.Href);                  __w.Write("\" target=\"_blank\">");                  __w.Write(info5.Title);                  __w.Write("</a><br />\r\n");              }              __w.Write("\r\n<hr />\r\n\r\n</body>\r\n</html>\r\n");          }           [DebuggerNonUserCode]          protected override void FrameworkInitialize()          {              base.FrameworkInitialize();              this.__BuildControlTree(this);              base.AddWrappedFileDependencies(__fileDependencies);              base.Request.ValidateInput();          }           [DebuggerNonUserCode]          public override int GetTypeHashCode()          {              return -1307842476;          }           [DebuggerNonUserCode]          public override void ProcessRequest(HttpContext context)          {              base.ProcessRequest(context);          }           protected global_asax ApplicationInstance          {              get              {                  return (global_asax) this.Context.ApplicationInstance;              }          }           protected DefaultProfile Profile          {              get              {                  return (DefaultProfile) this.Context.Profile;              }          }           protected override bool SupportAutoEvents          {              get              {                  return false;              }          }      }  }

請注意下面這段關鍵的代碼:它們實在太重要了。

private void __BuildControlTree(testpage_inlinepage_aspx __ctrl)  {     // .......       __ctrl.SetRenderMethodDelegate(new RenderMethod(this.__Render__control1));  }   private void __Render__control1(HtmlTextWriter __w, Control parameterContainer)  {

testpage_inlinepage_aspx與testpage_webfrompage_aspx的編譯結果完全不同。

最大的差別在testpage_inlinepage_aspx有個方法:__Render__control1

在這個方法中,頁面的內容將直接被寫入到HtmlTextWriter對象中。

還有一點我要告訴您:每個Control的輸出最后還是要將自己的顯示代碼寫入到HtmlTextWriter對象中。

因此,從這里就可以明顯地看出testpage_inlinepage_aspx的執行速度要快很多,

因為:

1. 它沒有服務器控件。

2. 不再需要遞歸循環每個控件,每個控件的生命周期的調用開銷也節省了。

3. 不用再創建那些服務器控件對象,GC的壓力會小很多。

4. 輸出方式更高效。

通過前面的分析,您現在明白了為什么二個頁面的執行速度相差6倍了原因了吧。

好像還有一點沒有解釋:__Render__control1如何被調用?

我們都知道:以ASPX頁面為代表的WebForm編程模型在執行時有一個特點:遞歸循環每個控件

頁面是在Render階段輸出的,頁面的HTML代碼也是在那個階段輸出到HtmlTextWriter對象中的。

可是,testpage_inlinepage_aspx沒有任何控件,那又該如何遞歸呢?

的確,很多書籍以及技術資料都是說:在Render階段會遞歸循環每個控件并調用控件的Render方法。

其實這種說法是不準確的。Control的Render方法在運行時,會調用下面這個方法:

internal void RenderChildrenInternal(HtmlTextWriter writer, ICollection children)  {      if ((this.RareFields != null) && (this.RareFields.RenderMethod != null))      {          writer.BeginRender();          this.RareFields.RenderMethod(writer, this);          writer.EndRender();      }      else if (children != null)      {          foreach (Control control in children)          {              control.RenderControl(writer);          }      }  }

這段代碼中,有個重要的if...else...判斷,簡單說來,就是說要不要調用前面所說的__Render__control1方法。

從代碼可以看出,如果是進入了if語句塊,則不用遞歸循環每個控件并調用控件的Render方法。

那么如何能進入if語句塊呢?

答案是:調用Control.SetRenderMethodDelegate方法。

testpage_inlinepage_aspx的編譯生成代碼中就有這個調用。

對于這個方法,MSDN的解釋很含糊:

此 API 支持 .NET Framework 基礎結構,不適合在代碼中直接使用。

分配事件處理程序委托,以將服務器控件及其內容呈現到父控件中。

ASP.NET頁面優化的方法

測試用例3:InlineUserControl.ascx

在測試用例3中,我將頁面中用于輸出的代碼移到一個用戶控件中。

用戶控件的代碼此處省略,與測試用例2的代碼基本上一致。編譯后的結果也基本差不多。

測試代碼:

[Action]  public object Test3(string callTimes)  {      int count = 0;      int.TryParse(callTimes, out count);      if( count <= 0 )          return count;       // 先執行一次,排除編譯時間      string html = MyMVC.UcExecutor.Render("/UserControl/InlineUserControl.ascx", null);            Stopwatch watch = Stopwatch.StartNew();      for( int i = 0; i < count; i++ )          html = MyMVC.UcExecutor.Render("/UserControl/InlineUserControl.ascx", null);      watch.Stop();       return watch.Elapsed.ToString();  }

當我測試執行10000次時,耗時:00:00:00.9132738

又快了一點。

說明:為了這次的性能優化,MyMVC框架也做了一點調整。如果您以前下載過這個框架,請重新下載。

ASP.NET頁面優化的方法

分析優化結果2

經過前面的分析,我們知道:不創建服務器控件對象以及不調用它們的生命周期,可以讓頁面的執行速度快很多。

有沒有再想像一下:頁面也有生命周期啊,而且生命周期的步驟更長,省略它,會不會更快呢?

不過,Render方法并不是個public方法,我們還不能直接調用,但可以調用RenderControl方法來實現這一過程。

由于跳過頁面的生命周期,任何服務器控件都不能使用了,包括母板頁。所以我選擇將前面測試用的那段代碼移到用戶控件中,然后將用戶控件加載到Page中來測試。

測試用例3與測試用例2相比,在測試過程中,由于跳過了頁面的生命周期,因此速度也就更快了。

注意:事實上,動態加載用戶控件也會有一定的調用開銷。這種方法也僅供參考,可以根據實際情況來選擇。

嗯,基本上,就是這個簡單的原因吧。

由于這種方法沒有任何的控件生命周期,因此速度是最快的。

經過這一系列的優化,頁面的執行時間最終由 00:00:07.5607229 減少到 00:00:00.9132738

再次申明:測試結果也僅僅只是一個參考數字。

事實上,使用服務器控件產生的對象涉及到GC的回收以及內存占用的影響也是不可忽視的。

關于ASP.NET頁面優化的方法就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

庄浪县| 吉木萨尔县| 沂南县| 神池县| 来安县| 杂多县| 梁河县| 鄂温| 金乡县| 内江市| 万宁市| 苏尼特右旗| 饶阳县| 辰溪县| 清徐县| 上杭县| 东兰县| 儋州市| 富顺县| 兴仁县| 会东县| 云南省| 大渡口区| 察雅县| 洛隆县| 红原县| 梁平县| 墨玉县| 隆化县| 建水县| 合山市| 政和县| 泗洪县| 阳城县| 陇南市| 南宁市| 镇江市| 商南县| 分宜县| 阿拉尔市| 六安市|