午夜视频免费看_日韩三级电影网站_国产精品久久一级_亚洲一级在线播放_人妻体内射精一区二区三区_91夜夜揉人人捏人人添红杏_91福利在线导航_国产又粗又猛又黄又爽无遮挡_欧美日韩一区在线播放_中文字幕一区二区三区四区不卡 _日日夜夜精品视频免费观看_欧美韩日一区二区三区

主頁 > 知識庫 > ASP.NET頁面優化 性能提升8倍的方法

ASP.NET頁面優化 性能提升8倍的方法

熱門標簽:地圖標注多個行程 銅川小型外呼系統運營商 海外地圖標注門市標 山西防封卡電銷卡套餐 廈門商鋪地圖標注 浙江外呼系統怎么安裝 云南外呼電銷機器人系統 陜西人工外呼系統哪家好 上海楊浦怎么申請申請400電話
為了讓您對優化的效果有個直觀的了解,我準備了下面的測試結果截圖:

測試環境:
1. Windows Server 2003 SP2
2. Viaual Studio 2008,使用自帶的WebDev.WebServer.EXE運行網站程序。
3. (ThinkPad SL510):Core2 T6670 2.2GHz, 4G內存

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

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

測試背景

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

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

真是這樣嗎?

今天測試的起點就從使用簡單的服務器開始,我會分二次對它做一系列的性能優化。
最終就是上圖中的3個結果,它們反映了二次優化的改進過程。

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

優化的過程涉及到ASP.NET服務器控件的使用,測試結果也僅僅只是一個參考數字。
如果您認為您的開發工作非常依賴于服務器控件的使用,
那么測試結果對您來說其實是無意義的,請不要在意這個結果。
測試方法
在這次優化過程中,我并沒有設計很復雜的測試頁面,而是一個很簡單的測試頁面,頁面顯示效果如下:

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

測試的數據是這樣獲取的:
我復制了我的博客側邊欄的【推薦排行榜】的那段HTML代碼,保存到一個文件中:

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

public class BlogInfo
{
public string Title;
public string Href;
}

public static class XmlDb
{
public static ListBlogInfo> 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框架。
測試用例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
回到頂部
測試用例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
回到頂部
分析優化結果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時,為了方便編譯網站而寫的一個小工具。
下載地址:https://www.jb51.net/article/29875.htm
注意:下載的是一個工具包,安裝后,從開始菜單中運行FishTools\FishAspnetTool即可。
下面是工具的運行截圖。

操作方法:
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\nhtml xmlns=\"http://www.w3.org/1999/xhtml\">\r\nhead>\r\n title>PagePerformanceTest http://www.cnblogs.com/fish-li//title>\r\n/head>\r\nbody>\r\n\r\np>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\nhtml xmlns=\"http://www.w3.org/1999/xhtml\">\r\nhead>\r\n title>PagePerformanceTest http://www.cnblogs.com/fish-li//title>\r\n/head>\r\nbody>\r\n\r\np>This is InlinePage.aspx/p>\r\n\r\n");
foreach (BlogInfo info in XmlDb.Blogs)
{
__w.Write("\r\n\ta href=\"");
__w.Write(info.Href);
__w.Write("\" target=\"_blank\">");
__w.Write(info.Title);
__w.Write("/a>br />\r\n");
}
__w.Write("\r\nhr />\r\n\r\n");
foreach (BlogInfo info2 in XmlDb.Blogs)
{
__w.Write("\r\n\ta href=\"");
__w.Write(info2.Href);
__w.Write("\" target=\"_blank\">");
__w.Write(info2.Title);
__w.Write("/a>br />\r\n");
}
__w.Write("\r\nhr />\r\n\r\n");
foreach (BlogInfo info3 in XmlDb.Blogs)
{
__w.Write("\r\n\ta href=\"");
__w.Write(info3.Href);
__w.Write("\" target=\"_blank\">");
__w.Write(info3.Title);
__w.Write("/a>br />\r\n");
}
__w.Write("\r\nhr />\r\n\r\n");
foreach (BlogInfo info4 in XmlDb.Blogs)
{
__w.Write("\r\n\ta href=\"");
__w.Write(info4.Href);
__w.Write("\" target=\"_blank\">");
__w.Write(info4.Title);
__w.Write("/a>br />\r\n");
}
__w.Write("\r\nhr />\r\n\r\n");
foreach (BlogInfo info5 in XmlDb.Blogs)
{
__w.Write("\r\n\ta href=\"");
__w.Write(info5.Href);
__w.Write("\" target=\"_blank\">");
__w.Write(info5.Title);
__w.Write("/a>br />\r\n");
}
__w.Write("\r\nhr />\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 基礎結構,不適合在代碼中直接使用。
分配事件處理程序委托,以將服務器控件及其內容呈現到父控件中。
回到頂部
測試用例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框架也做了一點調整。如果您以前下載過這個框架,請重新下載。
回到頂部
分析優化結果2
經過前面的分析,我們知道:不創建服務器控件對象以及不調用它們的生命周期,可以讓頁面的執行速度快很多。
有沒有再想像一下:頁面也有生命周期啊,而且生命周期的步驟更長,省略它,會不會更快呢?
不過,Render方法并不是個public方法,我們還不能直接調用,但可以調用RenderControl方法來實現這一過程。
由于跳過頁面的生命周期,任何服務器控件都不能使用了,包括母板頁。所以我選擇將前面測試用的那段代碼移到用戶控件中,然后將用戶控件加載到Page中來測試。
測試用例3與測試用例2相比,在測試過程中,由于跳過了頁面的生命周期,因此速度也就更快了。
嗯,基本上,就是這個簡單的原因吧。
由于這種方法沒有任何的控件生命周期,因此速度是最快的。
經過這一系列的優化,頁面的執行時間最終由 00:00:07.5607229 減少到 00:00:00.9132738

點擊此處下載示例代碼
您可能感興趣的文章:
  • ASP.NET 高性能分頁代碼
  • ASP.NET(C#) String, StringBuilder 與 StringWriter性能比較
  • asp.net 程序性能優化的七個方面 (c#(或vb.net)程序改進)
  • ASP.NET Session會導致的性能問題
  • 增加asp.net應用程序性能的20種方法(簡單有效)
  • ASP.NET 提高首頁性能的十大做法
  • ASP.NET性能優化小結(ASP.NETC#)
  • 打造基于jQuery的高性能TreeView(asp.net)
  • 分享提高ASP.NET Web應用性能的技巧

標簽:自貢 常州 信陽 萊蕪 許昌 朔州 孝感 西雙版納

巨人網絡通訊聲明:本文標題《ASP.NET頁面優化 性能提升8倍的方法》,本文關鍵詞  ASP.NET,頁面,優化,性能,提升,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《ASP.NET頁面優化 性能提升8倍的方法》相關的同類信息!
  • 本頁收集關于ASP.NET頁面優化 性能提升8倍的方法的相關信息資訊供網民參考!
  • 推薦文章
    色欲av无码一区二区三区| 97免费视频观看| 91精品国产乱码久久久久久久久| 亚洲人成网站在线| 伊人精品在线视频| 东京热无码av男人的天堂| 九九九九免费视频| 国产精品成人播放| 欧美一区二区日韩一区二区| 国产精品无遮挡| 成人毛片视频免费看| 三级电影在线看| 老司机午夜av| 欧洲美女和动交zoz0z| 51成人做爰www免费看网站| 日韩一区二区精品视频| 午夜精品福利一区二区蜜股av| 激情深爱一区二区| 青青国产在线视频| 亚洲精品乱码久久久久久不卡| 国产亚洲精品网站| 中文字幕日韩精品一区二区| 亚洲专区中文字幕| 国产成人精品视频在线观看| 日韩在线观看成人| 欧美日韩mp4| 欧美性极品xxxx娇小| 亚洲视频一区在线观看| 麻豆精品一区二区| 91成品人影院| 人人草在线观看| 在线观看成人毛片| 亚洲911精品成人18网站| 欧美大片在线播放| 免费毛片一区二区三区久久久| xvideos国产精品| 亚洲夜晚福利在线观看| 日韩精品视频在线观看网址| 欧美精品电影在线播放| 欧美亚洲图片小说| 黄色成人av网| 亚洲一二三四在线观看| 一区精品在线播放| 中文字幕一区二区三区精华液 | 日韩免费电影一区二区| 99热最新在线| 国内精品久久久久久久果冻传媒| 92看片淫黄大片看国产片| 日本少妇性生活| 97在线观看免费| 久久久久久久亚洲精品| www.国产一区| 欧美日韩成人在线观看| 欧美激情久久久| 欧美日本高清视频| 久久久久久av| 国产激情视频一区| 国产精品高潮呻吟久久av黑人| 91精品国产91久久久久久吃药| 隔壁老王国产在线精品| 韩日欧美一区二区| 国产精品久久99久久| 国产不卡一区二区在线播放| 欧美一级黄色网| 国产精品爽黄69| 国产精品区一区二区三在线播放| 精品久久久久久一区二区里番| 久久riav| 久久久成人精品一区二区三区| 91国在线高清视频| 国产超碰在线播放| 国产裸体视频网站| 免费在线观看你懂的| 久久精品视频免费在线观看| 香蕉免费毛片视频| 性活交片大全免费看| 亚洲色图 激情小说| 日本三级午夜理伦三级三| 亚洲视频一区在线播放| 久久久久久穴| www.欧美日韩国产在线| 亚洲欧美aⅴ...| 欧美日韩综合色| 亚洲欧洲国产伦综合| 97激碰免费视频| 国产精品一区在线观看| 中文精品无码中文字幕无码专区 | 亚洲一区二区自偷自拍 | 婷婷久久综合九色综合伊人色| 日韩欧美一级二级三级久久久| 最新中文字幕亚洲| 国产在线视频不卡| 9999在线观看| 国产免费无码一区二区| 麻豆一区二区三区精品视频| 亚洲av无码乱码国产精品久久| 国产河南妇女毛片精品久久久 | 尤物yw午夜国产精品视频明星| 2019亚洲男人天堂| 亚洲成人午夜在线| 一个人看的视频www| 国产精品自拍视频一区| 久久久噜噜噜| 亚洲男人天堂av| 国产丝袜一区二区| 成人妇女淫片aaaa视频| 蜜臀av性久久久久蜜臀av| 亚洲欧美日本一区| 国产口爆吞精一区二区| 久久久综合激的五月天| 91精品久久久久久久久99蜜臂| 久久久久久久久久av| 亚洲国产午夜伦理片大全在线观看网站| 污污的网站免费| 日韩精品在线观看免费| 成人免费毛片片v| 精品人妻久久久久一区二区三区| 亚洲精品国产一区二| 一区二区中文视频| 在线成人中文字幕| 欧美大香线蕉线伊人久久| 亚洲黄色小说在线观看| 99久久久久成人国产免费| 日本一区二区成人| 亚洲毛片在线观看| 日韩av一区二区三区在线观看| 大乳护士喂奶hd| 久久亚洲一区| 欧美日韩国产综合一区二区三区| 国产99久久精品一区二区永久免费| 日韩黄色片在线| a v视频在线观看| 国产日韩v精品一区二区| 国产亚洲精品一区二555| 精品视频久久久久久| 国产精品久久视频| 中文字幕永久视频| 中文字幕av影视| 亚洲一区二区成人在线观看| 色综合天天综合网国产成人网 | 亚洲精品自在久久| 亚洲一区二区不卡视频| 欧美日韩在线观看成人| 91麻豆国产福利在线观看| 国产亚洲欧洲高清一区| 福利在线小视频| 久久国产黄色片| 亚洲最色的网站| 成人欧美一区二区三区黑人孕妇 | 三级欧美在线一区| 精品久久久三级丝袜| 亚洲精品二区| 免费在线观看日韩视频| 国产 日韩 欧美 成人| 国产精品久久久久影院亚瑟| 久久久久久久久久久久av| 黄色三级视频在线| 无套内谢的新婚少妇国语播放| 色88888久久久久久影院按摩 | mm131美女视频| 成人免费毛片片v| 久久久久久国产免费| 性久久久久久久久久久久久久| 蜜臀av一级做a爰片久久| 亚洲欧洲日产国产网站| 日韩免费一级视频| 污视频软件在线观看| 亚洲精品不卡在线| 婷婷五月综合缴情在线视频| 国产手机精品视频| 精品国产乱码久久久久久1区2区| 麻豆中文字幕在线观看| 国产福利第一视频| 精品国产亚洲一区二区三区在线观看| 亚洲福利在线观看| 男女视频网站在线观看| 亚洲 小说区 图片区 都市| 日韩经典中文字幕| 色播五月综合网| heyzo一本久久综合| 日本久久精品视频| 三级黄色在线观看| 欧美日韩亚洲91| 一区二区三区在线观看www| 国产精品久久欧美久久一区| 欧美一区二区三区性视频| 国产 日韩 亚洲 欧美| 美女一区二区久久| 午夜免费久久久久| 影音先锋男人资源在线观看| 亚洲精品乱码久久久久久久久| 久久riav二区三区| 99久久久国产精品无码免费| 亚洲天堂日韩电影| 国产激情第一页| 亚洲精品乱码久久久久久| 九九九九精品九九九九| 午夜免费福利在线| 韩国精品免费视频| 国产精选久久久久久| youjizz在线视频| 亚洲精品在线看| 国产视频久久久久久| 亚洲图片欧美一区| 黄色片免费在线观看视频| 日本v片在线高清不卡在线观看| 久久免费精品视频| 日韩av男人天堂| 亚洲精品美女在线观看播放| 特级西西人体4444xxxx| 午夜激情久久久| 18禁免费无码无遮挡不卡网站| 国产91精品一区二区麻豆网站| 91麻豆国产语对白在线观看| 国产精品人妻一区二区三区| 欧美大尺度激情区在线播放| 成年人一级黄色片| 亚洲精品一区在线观看香蕉| av女人的天堂| 精品美女在线观看| 久久精品成人av| 美女视频网站黄色亚洲| 九九久久久久99精品| 日本五十熟hd丰满| 中文字幕在线亚洲| 日韩精品久久久久久久| 久久精品久久久久| 亚洲国产精一区二区三区性色| 亚洲日韩欧美视频一区| 五月天激情丁香| 亚洲精品日韩丝袜精品| 性色av无码久久一区二区三区| 国产亚洲激情在线| 久久精品免费av| 在线亚洲欧美视频| 国产精品一区无码| 69视频在线播放| 99re只有精品| 91在线观看免费高清| 精品一区二区在线看| 奇米影视首页 狠狠色丁香婷婷久久综合| 精品中文字幕一区二区| 性欧美大战久久久久久久免费观看| jizz一区二区| 国产精品网站免费| 亚洲6080在线| 国产黑丝一区二区| 亚洲欧洲视频在线| 中文字幕+乱码+中文字幕明步 | 亚洲综合网在线| 欧美黄色片在线观看| 国内精品久久久久久久久久| 亚洲综合自拍一区| 99久久久久久| 男人的天堂日韩| 5566中文字幕一区二区电影| 天天色天天综合| 国模精品视频一区二区| 日日欢夜夜爽一区| 亚洲精品日韩成人| 亚洲高清免费观看| 久久久久九九九九| 天天躁日日躁狠狠躁av麻豆男男| 欧美一区二区三区四区久久| 999精品在线视频| 国产91av在线| 国产精品18久久久久久久久| 可以在线看的av网站| 在线播放/欧美激情| 久久黄色精品视频| 成人蜜桃视频| 亚洲色图欧美激情| 日韩美女视频免费在线观看| 国产精品99久久久久久久vr| 国产一级不卡毛片| 国产丝袜高跟一区| 人妻一区二区三区四区| 熟女视频一区二区三区| 色婷婷综合久久久中文字幕| 久久久久久国产精品视频| 91精品国产综合久久男男 | www.超碰在线观看| 国产精品一区二区久久国产| 久久久久国产免费免费| www.超碰97| 国产97在线|日韩| 91片在线免费观看| 国产精品无码专区| 亚洲91精品在线| 久久色成人在线| www.av天天| 91久久久久久久| 亚洲国产精品影院| 日韩av女优在线观看| 日本a级片久久久| 欧美老人xxxx18| 秋霞av鲁丝片一区二区| 日本成人在线免费视频| 一区二区三区产品免费精品久久75| 日本高清免费观看| 欧美性视频精品| 日韩理论片网站| 国产午夜精品无码| 一级日韩一区在线观看| 亚洲第一页中文字幕| 日本亚洲最大的色成网站www| 亚洲欧美日本一区二区| 韩国精品美女www爽爽爽视频| 国产亚洲综合av| 久久久精品视频免费| 黄色影视在线观看| 在线成人一区二区| 99视频精品全部免费在线| 少妇高潮一区二区三区喷水| 免费国产在线精品一区二区三区| 日韩你懂的电影在线观看| 男男视频亚洲欧美| 国产不卡一二三| 国产91社区| 亚洲国产91色在线| eeuss影院一区二区三区| 国产色无码精品视频国产| 色播亚洲婷婷| 日韩中文字幕免费看| 中文字幕一区二区三区在线不卡| 免费视频久久久| 在线观看免费黄网站| 欧美日韩国产综合久久| 中文字幕第315页| 99热这里只有精品在线播放| 成人xxxxx| 日韩电影网在线| 国产欧美一区二区在线| av网站中文字幕| 男人添女人下面免费视频| 国产精品日韩欧美综合| 欧美军同video69gay| 床上的激情91.| 国产精品成人网站| 欧美日韩在线免费播放| 91久久在线观看| 日韩精品中文字幕有码专区| 中文在线免费一区三区高中清不卡| 在线免费一级片| 中文字幕 日本| 中文字幕一区二区三区四区五区| 久久国产天堂福利天堂| 欧美日韩国产精品一区| 久久99精品国产麻豆不卡| 久久影院一区二区| 国产主播中文字幕| 久久久福利视频| 欧美黑人xxxⅹ高潮交| 欧美日韩国产经典色站一区二区三区| 国产精品白丝av| 日本丰满少妇做爰爽爽| 美国黄色a级片| 欧洲精品在线播放| 99久久久精品免费观看国产 | 欧美精品亚洲精品| 97精品久久久| 精品亚洲永久免费精品| 偷拍亚洲欧洲综合| 2024国产精品| 亚洲xxxx天美| 国产精品不卡av| 中文成人无字幕乱码精品区| 国产一线二线三线女| 久久av一区二区| 国产精品大陆在线观看| 中文字幕综合一区| 91麻豆精品国产91久久久| 亚洲欧美在线视频观看| 丁香六月久久综合狠狠色| 色欲久久久天天天综合网| 中文字幕超碰在线| 精品成人无码一区二区三区| 国产极品在线视频| 亚洲国产日韩综合一区| 亚洲淫片在线视频| 国产91精品在线播放| 欧美老女人xx| 最近2019中文字幕第三页视频| 欧美高清视频一二三区| 亚洲成a天堂v人片| 亚洲色图一区二区三区| 久久蜜桃av一区精品变态类天堂| 精品一区二区免费在线观看| 五月婷婷丁香六月| 高清毛片aaaaaaaaa片| 18国产免费视频| 国产www在线| 不卡的免费av| 青青草免费av| 放荡的美妇在线播放| 欧美成人久久久免费播放| 美国黄色一级毛片| 国产熟妇搡bbbb搡bbbb| 精品人妻一区二区三区日产乱码卜| 日韩高清在线一区二区| 激情文学亚洲色图| 伊人国产在线视频| 亚洲美女性囗交| 奇米视频888| 欧美日韩久久婷婷| 在线免费黄色小视频| 精品国产免费久久久久久婷婷| av天堂一区二区| 男女一区二区三区| 日本高清黄色片|