ASP.NET页面性能提升8倍的优化方法

  第1页:

  【IT168 技术】阅读目录

  开始

  测试背景

  测试方法

  测试用例1:WebFromPage.aspx

  测试用例2:InlinePage.aspx

  分析优化结果1

  测试用例3:InlineUserControl.ascx

  分析优化结果2

  今天与大家分享:一种优化页面执行速度的方法。采用这个方法,可以使用页面的执行速度获得【8倍】的提升效果。为了让您对优化的效果有个直观的了解,我准备了下面的测试结果截图:

  

  ASP.NET页面性能提升8倍的优化方法


  测试环境:

  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的WebForm编程模型开始学习的。 大家都很喜欢用服务器控件,不管输出什么,都会使用服务器控件。 有时候为了让页面呈现干净的HTML代码,有些人会选择使用Repeater,Literal这类简单的服务器控件。 或许有些人认为:我已不使用GridView这样强大复杂的控件,页面执行速度已经很快了。

  真是这样吗?今天测试的起点就从使用简单的服务器开始,我会分二次对它做一系列的性能优化。

  最终就是上图中的3个结果,它们反映了二次优化的改进过程。在继续介绍之前,有一点我想有必要说明一下:

  优化的过程涉及到ASP.NET服务器控件的使用,测试结果也仅仅只是一个参考数字。

  如果您认为您的开发工作非常依赖于服务器控件的使用,

  那么测试结果对您来说其实是无意义的,请不要在意这个结果。

  测试方法

  在这次优化过程中,我并没有设计很复杂的测试页面,而是一个很简单的测试页面,页面显示效果如下:

  

  ASP.NET页面性能提升8倍的优化方法


  这个页面其实就是显示了一堆超链接,它们来自于我的博客侧边栏的【推荐排行榜】,总共有20条记录, 我让页面重复5次输出,也就是生成了100个超链接。

  测试的数据是这样获取的:

  我复制了我的博客侧边栏的【推荐排行榜】的那段HTML代码,保存到一个文件中:

  

  ASP.NET页面性能提升8倍的优化方法


  然后,网站在初始化时,从这段HTML代码提取链接地址以及显示文字,保存到一个BlogInfo的列表中,代码如下:

  

  

  public class BlogInfo

  public string Title;

  public string Href;

  public static class XmlDb

  public static List Blogs { get; private set; }

  public static void LoadBlogs()

  string filePath = Path.Combine(HttpRuntime.AppDomainAppPath, @App_DataRecommendList.html);

  XElement html = XElement.Parse(System.IO.File.ReadAllText(filePath));

  Blogs =

  (from a in html.Elements(li).Elements(a)

  我想这个测试还是比较接近于现实开发的。

  这里又有一个问题:我如何测试页面的执行速度?

  虽然说创建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.aspxp>

  asp:Repeater runat=server onitemdatabound=repeater1_ItemDataBound>

  ItemTemplate>

  asp:HyperLink runat=server>asp:HyperLink>br />

  ItemTemplate>

  FooterTemplate>hr />FooterTemplate>

  asp:Repeater>

  asp:Repeater runat=server onitemdatabound=repeater1_ItemDataBound>

  ItemTemplate>

  asp:HyperLink runat=server>asp:HyperLink>br />

  ItemTemplate>

  FooterTemplate>hr />FooterTemplate>

  asp:Repeater>

  asp:Repeater runat=server onitemdatabound=repeater1_ItemDataBound>

  ItemTemplate>

  asp:HyperLink runat=server>asp:HyperLink>br />

  ItemTemplate>

  FooterTemplate>hr />FooterTemplate>

  asp:Repeater>

  asp:Repeater runat=server onitemdatabound=repeater1_ItemDataBound>

  ItemTemplate>

  asp:HyperLink runat=server>asp:HyperLink>br />

  ItemTemplate>

  FooterTemplate>hr />FooterTemplate>

  asp:Repeater>

  asp:Repeater runat=server onitemdatabound=repeater1_ItemDataBound>

  ItemTemplate>

  asp:HyperLink 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)

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

  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.aspxp>

  % foreach( BlogInfo b in XmlDb.Blogs ) { %>

  a href= target=_blank>%= b.Title %>a>br />

  % } %>

  hr />

  % foreach( BlogInfo b in XmlDb.Blogs ) { %>

  a href= target=_blank>%= b.Title %>a>br />

  % } %>

  hr />

  % foreach( BlogInfo b in XmlDb.Blogs ) { %>

  a href= target=_blank>%= b.Title %>a>br />

  % } %>

  hr />

  % foreach( BlogInfo b in XmlDb.Blogs ) { %>

  a href= target=_blank>%= b.Title %>a>br />

  % } %>

  hr />

  % foreach( BlogInfo b in XmlDb.Blogs ) { %>

  a href= target=_blank>%= b.Title %>a>br />

  % } %>

  hr />

  body>

  html>
  测试代码:

  第2页:测试代码:

  

  

  [Action]

  public object Test2(string callTimes)

  int count = 0;

  int.TryParse(callTimes, out count);

  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时,为了方便编译网站而写的一个小工具。

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

  注意:下载的是一个工具包,安装后,从开始菜单中运行FishToolsFishAspnetTool即可。

  下面是工具的运行截图。

  

  ASP.NET页面性能提升8倍的优化方法


  操作方法:

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

  [DebuggerNonUserCode]

  private void __BuildControl__control11(Control __ctrl)

  IParserAccessor accessor = __ctrl;

  accessor.AddParsedSubObject(new LiteralControl( ));

  HyperLink link = this.__BuildControl__control12();

  accessor.AddParsedSubObject(link);

  accessor.AddParsedSubObject(new LiteralControl(

   ));

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

  [DebuggerNonUserCode]

  private void __BuildControl__control14(Control __ctrl)

  IParserAccessor accessor = __ctrl;

  accessor.AddParsedSubObject(new LiteralControl( ));

  HyperLink link = this.__BuildControl__control15();

  accessor.AddParsedSubObject(link);

  accessor.AddParsedSubObject(new LiteralControl(

   ));

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

  [DebuggerNonUserCode]

  private void __BuildControl__control2(Control __ctrl)

  IParserAccessor accessor = __ctrl;

  accessor.AddParsedSubObject(new LiteralControl( ));

  HyperLink link = this.__BuildControl__control3();

  accessor.AddParsedSubObject(link);

  accessor.AddParsedSubObject(new LiteralControl(

   ));

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

  [DebuggerNonUserCode]

  private void __BuildControl__control5(Control __ctrl)

  IParserAccessor accessor = __ctrl;

  accessor.AddParsedSubObject(new LiteralControl( ));

  HyperLink link = this.__BuildControl__control6();

  accessor.AddParsedSubObject(link);

  accessor.AddParsedSubObject(new LiteralControl(

   ));

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

  [DebuggerNonUserCode]

  private void __BuildControl__control8(Control __ctrl)

  IParserAccessor accessor = __ctrl;

  accessor.AddParsedSubObject(new LiteralControl( ));

  HyperLink link = this.__BuildControl__control9();

  accessor.AddParsedSubObject(link);

  accessor.AddParsedSubObject(new LiteralControl(

   ));

  [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( http://www.w3.org/1999/xhtml> 本页无标题

  This is WebFromPage.aspx

   ));

  Repeater repeater = this.__BuildControlrepeater1();

  accessor.AddParsedSubObject(repeater);

  accessor.AddParsedSubObject(new LiteralControl( ));

  Repeater repeater2 = this.__BuildControlrepeater2();

  accessor.AddParsedSubObject(repeater2);

  accessor.AddParsedSubObject(new LiteralControl( ));

  Repeater repeater3 = this.__BuildControlrepeater3();

  accessor.AddParsedSubObject(repeater3);

  accessor.AddParsedSubObject(new LiteralControl( ));

  Repeater repeater4 = this.__BuildControlrepeater4();

  accessor.AddParsedSubObject(repeater4);

  accessor.AddParsedSubObject(new LiteralControl( ));

  Repeater repeater5 = this.__BuildControlrepeater5();

  accessor.AddParsedSubObject(repeater5);

  accessor.AddParsedSubObject(new LiteralControl( ));

  [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( http://www.w3.org/1999/xhtml> 本页无标题

  This is InlinePage.aspx

   );

  foreach (BlogInfo info in XmlDb.Blogs)

  __w.Write(

  __w.Write(info.Href);

  __w.Write( target=_blank>);

  __w.Write(info.Title);

  __w.Write(

   );

  __w.Write( );

  foreach (BlogInfo info2 in XmlDb.Blogs)

  __w.Write(

  __w.Write(info2.Href);

  __w.Write( target=_blank>);

  __w.Write(info2.Title);

  __w.Write(

   );

  __w.Write( );

  foreach (BlogInfo info3 in XmlDb.Blogs)

  __w.Write(

  __w.Write(info3.Href);

  __w.Write( target=_blank>);

  __w.Write(info3.Title);

  __w.Write(

   );

  __w.Write( );

  foreach (BlogInfo info4 in XmlDb.Blogs)

  __w.Write(

  __w.Write(info4.Href);

  __w.Write( target=_blank>);

  __w.Write(info4.Title);

  __w.Write(

   );

  __w.Write( );

  foreach (BlogInfo info5 in XmlDb.Blogs)

  __w.Write(

  __w.Write(info5.Href);

  __w.Write( target=_blank>);

  __w.Write(info5.Title);

  __w.Write(

   );

  __w.Write( );

  [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)

  {}
  第3页:测试用例3:InlineUserControl.ascx

  在测试用例3中,我将页面中用于输出的代码移到一个用户控件中。

  用户控件的代码此处省略,与测试用例2的代码基本上一致。编译后的结果也基本差不多。

  测试代码:

  

  

  [Action]

  public object Test3(string callTimes)

  int count = 0;

  int.TryParse(callTimes, out count);

  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

  再次申明:测试结果也仅仅只是一个参考数字。

  事实上,使用服务器控件产生的对象涉及到GC的回收以及内存占用的影响也是不可忽视的。


来源:腾讯 作者:

免责声明:本文仅代表作者个人观点,与世界朋友网无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。

[责任编辑:世界朋友]