技术开发 频道

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

  测试代码:

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

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

  注意:下载的是一个工具包,安装后,从开始菜单中运行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\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)

  {}

0
相关文章