亚洲综合原千岁中文字幕_国产精品99久久久久久久vr_无码人妻aⅴ一区二区三区浪潮_成人h动漫精品一区二区三

主頁(yè) > 知識(shí)庫(kù) > ASP.NET頁(yè)面優(yōu)化 性能提升8倍的方法

ASP.NET頁(yè)面優(yōu)化 性能提升8倍的方法

熱門標(biāo)簽:地圖標(biāo)注多個(gè)行程 銅川小型外呼系統(tǒng)運(yùn)營(yíng)商 海外地圖標(biāo)注門市標(biāo) 山西防封卡電銷卡套餐 廈門商鋪地圖標(biāo)注 浙江外呼系統(tǒng)怎么安裝 云南外呼電銷機(jī)器人系統(tǒng) 陜西人工外呼系統(tǒng)哪家好 上海楊浦怎么申請(qǐng)申請(qǐng)400電話
為了讓您對(duì)優(yōu)化的效果有個(gè)直觀的了解,我準(zhǔn)備了下面的測(cè)試結(jié)果截圖:

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

二個(gè)紅框中的數(shù)字反映了優(yōu)化前后的執(zhí)行時(shí)間。

數(shù)字表明:優(yōu)化前后,執(zhí)行時(shí)間有了8倍多的差別。

測(cè)試背景

看過(guò)了優(yōu)化結(jié)果,再來(lái)介紹一下:這個(gè)測(cè)試到底是在測(cè)試什么東西?

現(xiàn)在有很多做ASP.NET的開(kāi)發(fā)人員,應(yīng)該都是從ASP.NET的WebForm編程模型開(kāi)始學(xué)習(xí)的。大家都很喜歡用服務(wù)器控件,不管輸出什么,都會(huì)使用服務(wù)器控件。有時(shí)候?yàn)榱俗岉?yè)面呈現(xiàn)干凈的HTML代碼,有些人會(huì)選擇使用Repeater,Literal這類簡(jiǎn)單的服務(wù)器控件。或許有些人認(rèn)為:我已不使用GridView這樣強(qiáng)大復(fù)雜的控件,頁(yè)面執(zhí)行速度已經(jīng)很快了。

真是這樣嗎?

今天測(cè)試的起點(diǎn)就從使用簡(jiǎn)單的服務(wù)器開(kāi)始,我會(huì)分二次對(duì)它做一系列的性能優(yōu)化。
最終就是上圖中的3個(gè)結(jié)果,它們反映了二次優(yōu)化的改進(jìn)過(guò)程。

在繼續(xù)介紹之前,有一點(diǎn)我想有必要說(shuō)明一下:

優(yōu)化的過(guò)程涉及到ASP.NET服務(wù)器控件的使用,測(cè)試結(jié)果也僅僅只是一個(gè)參考數(shù)字。
如果您認(rèn)為您的開(kāi)發(fā)工作非常依賴于服務(wù)器控件的使用,
那么測(cè)試結(jié)果對(duì)您來(lái)說(shuō)其實(shí)是無(wú)意義的,請(qǐng)不要在意這個(gè)結(jié)果。
測(cè)試方法
在這次優(yōu)化過(guò)程中,我并沒(méi)有設(shè)計(jì)很復(fù)雜的測(cè)試頁(yè)面,而是一個(gè)很簡(jiǎn)單的測(cè)試頁(yè)面,頁(yè)面顯示效果如下:

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

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

然后,網(wǎng)站在初始化時(shí),從這段HTML代碼提取鏈接地址以及顯示文字,保存到一個(gè)BlogInfo的列表中,代碼如下:
復(fù)制代碼 代碼如下:

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

測(cè)試時(shí),就把XmlDb.Blogs的內(nèi)容顯示在網(wǎng)頁(yè)中。
我想這個(gè)測(cè)試還是比較接近于現(xiàn)實(shí)開(kāi)發(fā)的。

這里又有一個(gè)問(wèn)題:我如何測(cè)試頁(yè)面的執(zhí)行速度?

雖然說(shuō)創(chuàng)建HttpWebRequest訪問(wèn)頁(yè)面是個(gè)很簡(jiǎn)單的方法,但我并不打算這樣做。
因?yàn)閺腍ttpWebRequest發(fā)起調(diào)用到獲取結(jié)果,這其中除了有頁(yè)面的執(zhí)行時(shí)間,還混雜較多的額外調(diào)用開(kāi)銷。最終,我選擇了在一次HTTP請(qǐng)求中,循環(huán)調(diào)用Server.Execute來(lái)執(zhí)行頁(yè)面,并統(tǒng)計(jì)時(shí)間的方式。其實(shí)如何選擇測(cè)試方法,對(duì)于二個(gè)測(cè)試對(duì)象還說(shuō),都是公平的。只是說(shuō):盡量減少一些額外的調(diào)用開(kāi)銷,會(huì)讓測(cè)試結(jié)果的差異更大,也更明顯。

說(shuō)明:為了測(cè)試代碼寫(xiě)起來(lái)簡(jiǎn)單,我使用了MyMVC框架。
測(cè)試用例1:WebFromPage.aspx
前面介紹了測(cè)試背景以及測(cè)試方法。現(xiàn)在就來(lái)介紹第1個(gè)測(cè)試用例,它采用了WebForm編程模型中最經(jīng)典的寫(xiě)法。
頁(yè)面代碼:
復(fù)制代碼 代碼如下:

%@ 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>

頁(yè)面的CodeFile代碼:
復(fù)制代碼 代碼如下:

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;
}
}
}

測(cè)試代碼:
復(fù)制代碼 代碼如下:

[Action]
public object Test1(string callTimes)
{
int count = 0;
int.TryParse(callTimes, out count);
if( count = 0 )
return count;
HttpContext context = HttpContext.Current;
// 先執(zhí)行一次,排除編譯時(shí)間
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();
}

當(dāng)我測(cè)試執(zhí)行10000次時(shí),耗時(shí):00:00:07.5607229
回到頂部
測(cè)試用例2:InlinePage.aspx
與測(cè)試用例1不同,測(cè)試用例2則完全不使用服務(wù)器控件。
頁(yè)面代碼:
復(fù)制代碼 代碼如下:

%@ 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>

測(cè)試代碼:
復(fù)制代碼 代碼如下:

[Action]
public object Test2(string callTimes)
{
int count = 0;
int.TryParse(callTimes, out count);
if( count = 0 )
return count;
HttpContext context = HttpContext.Current;
// 先執(zhí)行一次,排除編譯時(shí)間
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();
}

當(dāng)我測(cè)試執(zhí)行10000次時(shí),耗時(shí):00:00:01.2345842
回到頂部
分析優(yōu)化結(jié)果1
測(cè)試用例1執(zhí)行相同次數(shù)所花費(fèi)的時(shí)間是測(cè)試用例2的6倍,為什么會(huì)這樣呢?
為了回答這個(gè)問(wèn)題,我們首先要知道前面二個(gè)頁(yè)面在執(zhí)行時(shí),它們是如何運(yùn)行的。
說(shuō)到這里,就不得不談ASP.NET的頁(yè)面編譯方式了。
ASP.NET的頁(yè)面編譯過(guò)程是個(gè)復(fù)雜的操作,其實(shí)我們可以不用關(guān)心頁(yè)面是如何編譯的,
但要知道:頁(yè)面編譯后是什么樣的。
為了能直觀地了解頁(yè)面編譯后的樣子,我編譯了整個(gè)網(wǎng)站,并生成到一個(gè)DLL文件中,然后使用Reflector.exe來(lái)分析這個(gè)DLL的源代碼。
將網(wǎng)站編譯成一個(gè)DLL文件有二個(gè)方法:
1. 安裝WebDeployment插件。
2. 使用我的工具:FishAspnetTool
本文將使用FishAspnetTool來(lái)編譯測(cè)試網(wǎng)站獲得編譯后的DLL文件。
FishAspnetTool是什么?
FishAspnetTool是我在使用Visual Web Developer 2005時(shí),為了方便編譯網(wǎng)站而寫(xiě)的一個(gè)小工具。
下載地址:https://www.jb51.net/article/29875.htm
注意:下載的是一個(gè)工具包,安裝后,從開(kāi)始菜單中運(yùn)行FishTools\FishAspnetTool即可。
下面是工具的運(yùn)行截圖。

操作方法:
1. 點(diǎn)擊粉色按鈕,選擇網(wǎng)站路徑。
2. 單選按鈕選擇第2項(xiàng)。
3. 點(diǎn)擊【發(fā)布網(wǎng)站】按鈕。
在編譯網(wǎng)站之后,我就可以知道網(wǎng)站在運(yùn)行時(shí)如何運(yùn)行頁(yè)面了。
測(cè)試用例1的頁(yè)面,最后被編譯成這樣了:
復(fù)制代碼 代碼如下:

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;
}
}
}
}

從這個(gè)編譯結(jié)果我們可以看出:頁(yè)面上的所有文字最后也被包裝到LiteralControl中。
頁(yè)面中呈現(xiàn)時(shí),就是循環(huán)調(diào)用每個(gè)控件的Render方法來(lái)最終生成HTML結(jié)果。
測(cè)試用例2的頁(yè)面被編譯成這個(gè)樣了:
復(fù)制代碼 代碼如下:

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;
}
}
}
}

請(qǐng)注意下面這段關(guān)鍵的代碼:它們實(shí)在太重要了。
復(fù)制代碼 代碼如下:

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的編譯結(jié)果完全不同。
最大的差別在testpage_inlinepage_aspx有個(gè)方法:__Render__control1
在這個(gè)方法中,頁(yè)面的內(nèi)容將直接被寫(xiě)入到HtmlTextWriter對(duì)象中。
還有一點(diǎn)我要告訴您:每個(gè)Control的輸出最后還是要將自己的顯示代碼寫(xiě)入到HtmlTextWriter對(duì)象中。
因此,從這里就可以明顯地看出testpage_inlinepage_aspx的執(zhí)行速度要快很多,
因?yàn)椋?
1. 它沒(méi)有服務(wù)器控件。
2. 不再需要遞歸循環(huán)每個(gè)控件,每個(gè)控件的生命周期的調(diào)用開(kāi)銷也節(jié)省了。
3. 不用再創(chuàng)建那些服務(wù)器控件對(duì)象,GC的壓力會(huì)小很多。
4. 輸出方式更高效。
通過(guò)前面的分析,您現(xiàn)在明白了為什么二個(gè)頁(yè)面的執(zhí)行速度相差6倍了原因了吧。
好像還有一點(diǎn)沒(méi)有解釋:__Render__control1如何被調(diào)用?
我們都知道:以ASPX頁(yè)面為代表的WebForm編程模型在執(zhí)行時(shí)有一個(gè)特點(diǎn):遞歸循環(huán)每個(gè)控件。
頁(yè)面是在Render階段輸出的,頁(yè)面的HTML代碼也是在那個(gè)階段輸出到HtmlTextWriter對(duì)象中的。
可是,testpage_inlinepage_aspx沒(méi)有任何控件,那又該如何遞歸呢?
的確,很多書(shū)籍以及技術(shù)資料都是說(shuō):在Render階段會(huì)遞歸循環(huán)每個(gè)控件并調(diào)用控件的Render方法。
其實(shí)這種說(shuō)法是不準(zhǔn)確的。Control的Render方法在運(yùn)行時(shí),會(huì)調(diào)用下面這個(gè)方法:
復(fù)制代碼 代碼如下:

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);
}
}
}

這段代碼中,有個(gè)重要的if...else...判斷,簡(jiǎn)單說(shuō)來(lái),就是說(shuō)要不要調(diào)用前面所說(shuō)的__Render__control1方法。
從代碼可以看出,如果是進(jìn)入了if語(yǔ)句塊,則不用遞歸循環(huán)每個(gè)控件并調(diào)用控件的Render方法。
那么如何能進(jìn)入if語(yǔ)句塊呢?
答案是:調(diào)用Control.SetRenderMethodDelegate方法。
testpage_inlinepage_aspx的編譯生成代碼中就有這個(gè)調(diào)用。
對(duì)于這個(gè)方法,MSDN的解釋很含糊:
此 API 支持 .NET Framework 基礎(chǔ)結(jié)構(gòu),不適合在代碼中直接使用。
分配事件處理程序委托,以將服務(wù)器控件及其內(nèi)容呈現(xiàn)到父控件中。
回到頂部
測(cè)試用例3:InlineUserControl.ascx
在測(cè)試用例3中,我將頁(yè)面中用于輸出的代碼移到一個(gè)用戶控件中。
用戶控件的代碼此處省略,與測(cè)試用例2的代碼基本上一致。編譯后的結(jié)果也基本差不多。
測(cè)試代碼:
復(fù)制代碼 代碼如下:

[Action]
public object Test3(string callTimes)
{
int count = 0;
int.TryParse(callTimes, out count);
if( count = 0 )
return count;
// 先執(zhí)行一次,排除編譯時(shí)間
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();
}

當(dāng)我測(cè)試執(zhí)行10000次時(shí),耗時(shí):00:00:00.9132738
又快了一點(diǎn)。
說(shuō)明:為了這次的性能優(yōu)化,MyMVC框架也做了一點(diǎn)調(diào)整。如果您以前下載過(guò)這個(gè)框架,請(qǐng)重新下載。
回到頂部
分析優(yōu)化結(jié)果2
經(jīng)過(guò)前面的分析,我們知道:不創(chuàng)建服務(wù)器控件對(duì)象以及不調(diào)用它們的生命周期,可以讓頁(yè)面的執(zhí)行速度快很多。
有沒(méi)有再想像一下:頁(yè)面也有生命周期啊,而且生命周期的步驟更長(zhǎng),省略它,會(huì)不會(huì)更快呢?
不過(guò),Render方法并不是個(gè)public方法,我們還不能直接調(diào)用,但可以調(diào)用RenderControl方法來(lái)實(shí)現(xiàn)這一過(guò)程。
由于跳過(guò)頁(yè)面的生命周期,任何服務(wù)器控件都不能使用了,包括母板頁(yè)。所以我選擇將前面測(cè)試用的那段代碼移到用戶控件中,然后將用戶控件加載到Page中來(lái)測(cè)試。
測(cè)試用例3與測(cè)試用例2相比,在測(cè)試過(guò)程中,由于跳過(guò)了頁(yè)面的生命周期,因此速度也就更快了。
嗯,基本上,就是這個(gè)簡(jiǎn)單的原因吧。
由于這種方法沒(méi)有任何的控件生命周期,因此速度是最快的。
經(jīng)過(guò)這一系列的優(yōu)化,頁(yè)面的執(zhí)行時(shí)間最終由 00:00:07.5607229 減少到 00:00:00.9132738

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

標(biāo)簽:自貢 常州 信陽(yáng) 萊蕪 許昌 朔州 孝感 西雙版納

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《ASP.NET頁(yè)面優(yōu)化 性能提升8倍的方法》,本文關(guān)鍵詞  ASP.NET,頁(yè)面,優(yōu)化,性能,提升,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《ASP.NET頁(yè)面優(yōu)化 性能提升8倍的方法》相關(guān)的同類信息!
  • 本頁(yè)收集關(guān)于ASP.NET頁(yè)面優(yōu)化 性能提升8倍的方法的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    亚洲第一页乱| 麻豆午夜视频| 国产伦精品一区三区视频| 国产麻豆精品免费密入口| 国产伦精品一区二区三区在线观看| 国产国语对白一级毛片| 色综合久久天天综线观看| 香蕉视频一级| 四虎影视库| 九九久久99综合一区二区| 免费毛片播放| 99色精品| 精品久久久久久中文字幕2017| 日本特黄一级| 四虎精品在线观看| 日韩在线观看视频黄| 一a一级片| 日韩中文字幕一区| 久久精品欧美一区二区| 九九精品在线播放| 欧美大片aaaa一级毛片| 欧美一区二区三区性| 四虎精品在线观看| 九九免费精品视频| 韩国毛片基地| 日韩专区在线播放| 日本在线www| 国产精品12| 青青青草影院| 麻豆网站在线免费观看| 精品视频在线看| 久久99中文字幕| 九九免费精品视频| 韩国三级一区| 韩国三级视频网站| 国产一区二区高清视频| 高清一级做a爱过程不卡视频| 日韩专区一区| 高清一级做a爱过程不卡视频| 精品视频在线观看免费| 99久久精品国产国产毛片| 日韩在线观看免费| 毛片电影网| 国产视频一区二区三区四区| 999久久66久6只有精品| 可以免费在线看黄的网站| 二级特黄绝大片免费视频大片| 国产精品123| 国产高清视频免费| 国产麻豆精品hdvideoss| 欧美激情影院| 亚欧成人乱码一区二区| 亚洲爆爽| 久久精品欧美一区二区| 青青青草影院| 日本特黄特黄aaaaa大片| 国产一区二区精品| 国产91精品一区二区| 日本乱中文字幕系列| 中文字幕一区二区三区 精品| 99久久精品国产高清一区二区 | 欧美日本二区| 久久国产一区二区| 国产一区二区精品在线观看| 久草免费在线视频| 久久国产精品自线拍免费| 午夜家庭影院| 日韩专区亚洲综合久久| 国产不卡在线播放| 日韩欧美一二三区| 国产伦精品一区二区三区无广告| 韩国三级香港三级日本三级| 国产成人精品影视| 亚洲天堂免费观看| 亚洲 男人 天堂| 麻豆午夜视频| 91麻豆爱豆果冻天美星空| 国产麻豆精品高清在线播放| 好男人天堂网 久久精品国产这里是免费 国产精品成人一区二区 男人天堂网2021 男人的天堂在线观看 丁香六月综合激情 | 成人高清视频免费观看| 免费国产在线观看不卡| 亚洲女人国产香蕉久久精品| 日韩欧美一及在线播放| 青青青草影院| 台湾毛片| 亚欧乱色一区二区三区| 精品国产一区二区三区久 | 好男人天堂网 久久精品国产这里是免费 国产精品成人一区二区 男人天堂网2021 男人的天堂在线观看 丁香六月综合激情 | 国产极品白嫩美女在线观看看| 青青久久精品| 欧美夜夜骑 青草视频在线观看完整版 久久精品99无色码中文字幕 欧美日韩一区二区在线观看视频 欧美中文字幕在线视频 www.99精品 香蕉视频久久 | 国产成人精品影视| 欧美另类videosbestsex视频| 亚飞与亚基在线观看| 国产国产人免费视频成69堂| 久久99这里只有精品国产| 日本久久久久久久 97久久精品一区二区三区 狠狠色噜噜狠狠狠狠97 日日干综合 五月天婷婷在线观看高清 九色福利视频 | 黄视频网站免费看| 在线观看成人网 | 亚洲爆爽| 午夜精品国产自在现线拍| 日本免费乱理伦片在线观看2018| 国产亚洲精品aaa大片| 精品在线视频播放| 超级乱淫伦动漫| 国产一区二区精品久久91| 亚洲第一页乱| 韩国妈妈的朋友在线播放| 中文字幕Aⅴ资源网| 国产不卡高清在线观看视频| 国产伦精品一区三区视频| 国产伦精品一区二区三区在线观看| 午夜激情视频在线播放| 精品视频在线观看一区二区 | 精品国产一区二区三区免费| 欧美夜夜骑 青草视频在线观看完整版 久久精品99无色码中文字幕 欧美日韩一区二区在线观看视频 欧美中文字幕在线视频 www.99精品 香蕉视频久久 | 四虎影视库| 亚洲精品久久玖玖玖玖| 免费一级片网站| 国产一区二区精品久| 精品国产香蕉在线播出| 国产91精品一区二区| 尤物视频网站在线观看| 欧美爱爱动态| 麻豆系列国产剧在线观看| 高清一级做a爱过程不卡视频| 免费一级片在线观看| 一级毛片看真人在线视频| 日日日夜夜操| 尤物视频网站在线观看| 国产一区二区高清视频| 韩国毛片基地| 国产91视频网| 亚洲天堂免费观看| 亚洲 国产精品 日韩| 亚欧成人毛片一区二区三区四区| 亚欧成人毛片一区二区三区四区| 欧美激情一区二区三区中文字幕| 青青久久精品| 美女免费黄网站| 国产91素人搭讪系列天堂| 国产麻豆精品视频| 亚欧成人毛片一区二区三区四区| 日本免费看视频| 99色视频在线观看| 国产视频在线免费观看| 99色视频在线| 国产美女在线观看| 日韩中文字幕在线亚洲一区| 日本久久久久久久 97久久精品一区二区三区 狠狠色噜噜狠狠狠狠97 日日干综合 五月天婷婷在线观看高清 九色福利视频 | 欧美夜夜骑 青草视频在线观看完整版 久久精品99无色码中文字幕 欧美日韩一区二区在线观看视频 欧美中文字幕在线视频 www.99精品 香蕉视频久久 | 天天做人人爱夜夜爽2020| 精品国产一区二区三区久| 国产不卡高清在线观看视频| 毛片电影网| 美女免费毛片| 午夜精品国产自在现线拍| 国产a网| 国产91精品一区| 99久久精品国产国产毛片| 国产网站免费| 欧美爱爱动态| 亚欧成人乱码一区二区| 九九精品在线播放| 国产一区二区高清视频| a级黄色毛片免费播放视频| 午夜久久网| 欧美a级成人淫片免费看| 可以免费看毛片的网站| 在线观看成人网 | 黄视频网站免费看| 国产美女在线一区二区三区| 九九久久99综合一区二区| 日本乱中文字幕系列| 欧美大片a一级毛片视频| 成人高清护士在线播放| 国产成人女人在线视频观看| 九九精品久久| 日本特黄特黄aaaaa大片| 国产麻豆精品免费密入口| 国产视频一区二区在线播放| 国产不卡在线看| 天天做日日爱| 美女被草网站| 久久精品大片| 国产亚洲精品成人a在线| 香蕉视频三级| 美女免费黄网站| 国产视频网站在线观看| 国产一区二区精品尤物| 日本伦理片网站| 精品视频在线观看视频免费视频| 国产视频在线免费观看| 成人免费高清视频| 精品在线免费播放| 日韩在线观看视频免费| 国产a视频| 亚洲精品影院| 日本免费区| 精品国产一区二区三区国产馆|