技术开发 频道

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

        【IT168 技术】阅读目录

  开始

  测试背景

  测试方法

  测试用例1:WebFromPage.aspx

  测试用例2:InlinePage.aspx

  分析优化结果1

  测试用例3:InlineUserControl.ascx

  分析优化结果2

  今天与大家分享:一种优化页面执行速度的方法。采用这个方法,可以使用页面的执行速度获得【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服务器控件的使用,测试结果也仅仅只是一个参考数字。

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

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

  测试方法

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


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

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

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


  然后,网站在初始化时,从这段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_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>

 

0
相关文章