原文
标题:ASP.NET Best Practices for High Performance Applications
作者:Ali Khan (OKC)
链接:http://www.codeproject.com/aspnet/ASPNET_Best_Practices.asp
翻译时间:2007-11-20
摘要
文章列出了一些能使你的ASP.NET应用程式最优化的一些技术。它提供了一些共同的问题,设计方针,以及一些编程技巧,让你可以建置最佳的和健壮的解决方案。
简介【Introduction】
ASP.NET比传统的ASP强大得多,然而了解怎么使用它的强大去建立一个高效的、可靠的、健壮的程式也是很重要的。在此篇章中,我尝试突出一些关键的技巧,让你能使用它去尽可能地优化你的ASP.NET页面。篇幅可能比较长,我只能强调最重要的一些点。
1. 先计划调查,再做开发【Plan and research before you develop】
研究和调查.NET怎么使用才能真的有利于你。.NET为各个层次的应用程式设计和开发提供能各种各样的方案。这需要你要非常了解你自身的状况,以及每个能达到你目的的开发环境的好与坏。Visual Studio是一个全面的开发包,为实现同一个业务逻辑可提供能许多选项。检查每一个选项,并且为你即将来临的任务选择最适合的方案是非常重要的。用分层的手法,逻辑上划分你的应用程式:表现层、业务层和数据层。这不仅能让你能创建可维护代码,并允许你分别监控和优化每一层的性能。同时,清晰的逻辑分层也为程式的伸缩性提供了更多的选择。尝试减少你在code-behind文件的代码量,可以改善程式的维护性和伸缩性。
2. 字符串的串联【String concatenation】
如果处理不当,字符串的链接真的会导致程式性能的下降。你可以用以下两个方式串联字符串。
第一,在使用字符串的时候,直接添加新的字符串到现有的字符串。然而,这样的做法是非常消耗性能的(特别是你在循环中使用这种串联字符串)。当你添加新的字符串到现有的字符串时,.NET框架会先同时复制已存在和新的数据到内存进行串连,然后删除已存在的字符串,最后在新的字符串读出数据。过分冗长的串联字符串操作会非常消耗时间。
第二,也是比较好的办法,使用StringBuilder串联字符串。以下两个例子做相同的实现。如果你考虑使用哪种字符串串联方式,请你自己亲自分别测试一下两段程式。也许你会对结果非常意外。
'使用“+=”串联字符串
Response.Write("<b>String Class</b>")
Dim str As String = ""
Dim startTime As DateTime = DateTime.Now
Response.Write(("<br>Start time:" + startTime.ToString()))
Dim i As Integer
For i = 0 To 99999
str += i.ToString()
Next i
Dim EndTime As DateTime = DateTime.Now
Response.Write(("<br>End time:" + EndTime.ToString()))
Response.Write(("<br># of time Concatenated: " + i.ToString))
Results: 花了4分23秒完成100,000次串联
String Class
Start time: 2/15/2006 10:21:24 AM
End time: 2/15/2006 10:25:47 AM
# of time Concatenated: 100000
'使用“StringBuilder”串联字符串
Response.Write("<b>StringBuilder Class</b>")
Dim strbuilder As New StringBuilder()
Dim startTime As DateTime = DateTime.Now
Response.Write(("<br>Start time:" + startTime.ToString()))
Dim i As Integer
For i = 0 To 99999
strbuilder.Append(i.ToString())
Next i
Dim EndTime As DateTime = DateTime.Now
Response.Write(("<br>Stop time:" + EndTime.ToString()))
Response.Write(("<br># of time Concatenated: " + i.ToString))
Results: 1秒内完成100,000次串联
StringBuilder Class
Start time: 2/15/2006 10:31:22 AM
Stop time:2/15/2006 10:31:22 AM
# of time Concatenated: 100000
/*********************************************/
【我的C#版测试】
class Program
{
static void Main(string[] args)
{
StringConnect();
StringBuilderConnect();
}
static int loopTime = 100000;
private static void StringConnect()
{
DateTime start = DateTime.Now;
string str = "";
for (int i = 0; i < loopTime;i++ )
{
str += i.ToString();
}
Console.WriteLine("String:{0}"
, ((TimeSpan)(DateTime.Now - start)).TotalSeconds);
}
private static void StringBuilderConnect()
{
DateTime start = DateTime.Now;
StringBuilder str = new StringBuilder() ;
for (int i = 0; i < loopTime; i++)
{
str.Append(i.ToString());
}
Console.WriteLine("StringBuilder:{0}"
, ((TimeSpan)(DateTime.Now - start)).TotalSeconds);
}
}
结果:
String :151.5579296秒
StringBuilder : 0.0600864秒
/*********************************************/
这是ASP.NET在许多情况下能提供一种能极大地提高性能优于传统ASP的其中一种。
3. 避免信息回传提交服务器【Avoid round trips to the server】
你可以使用以下一些技巧去避免不必要的回传网站服务器:
- 尽可能地实现Ajax的UI。这个想法可以避免真个页面的刷新,并且只更新页面需要更新的一部分。在Scott's article(http://weblogs.asp.net/scottgu/archive/2006/01/01/434314.aspx)给了很多怎样使用Ajax Atlas和<atlas:updatepanel> 控件的一些很好的建议。
- 使用客户端脚本。客户端验证可以帮助减少一些需要处理用户的请求。在ASP.NET,你也可以使用客户端控件去验证用户的输入。
- 使用Page.ISPostBack属性,确认你只需在页面第一次初始化加载时呈现出来的信息,不在客户回传事件中也会响应。
If Not IsPostBack Then
LoadJScripts()
End If
- 在某些情况下,不必要处理回传事件。你可以使用client callbacks 去从服务器端获取数据,代替整个页面的回传。详细请看http://msdn2.microsoft.com/en-us/library/ms178208.aspx。
4. 当必要时才使用viewstate【Save viewstate only when necessary】
ViewState 主要被用于服务器控件在回传页面数据时能保持它自身的状态。这些信息会传到客户端,从一个hidden的变量读取回来。ViewState 不必要存在在不需要它的页面。随着ViewState数据的扩大,会影响垃圾回收的性能。你可以根据以下的一些提示。以便优化使用ViewState。
1)当你不需要ViewState的情况
在ASP.NET默认的状况下,ViewState的状态是开启的。你不需要ViewState的原因可能是你的页面只是用来输出数据而已,或者你已经明确用户的每次请求你都重新加载页面。以下情况下,你不需要使用ViewState。
a.你的页面不需要回传(postback)。如果页面不会回传信息给自己,或者页面只是用于输出数据,又或者页面不需要处理回应数据,你就不需要ViewState。
b.你不使用服务器事件。如果你的服务器控件不处理事件;服务器控件不是动态的或没有数据绑定属性值,或者他们在每次请求中都会在代码中进行重新设置属性值,你就不需要ViewState。
c.你会在每次页面刷新重新设置控件。如果你忽略旧数据,你在每次页面刷新的时候会重新设置服务器控件。你就不需要ViewState。
2)禁用ViewState
有几个方法可以不同程度禁用ViewState。
a.禁用在页面上单个控件的ViewState,把控件的EnableViewState属性设为false。
b.禁用单个页面的ViewState,在@ Page 的EnableViewState 属性指定为false。如:
<%@ Page EnableViewState="false" %>
c.在指定程式禁用ViewState,可以在相关程式的Web.config 文件中添加以下元素:
<pages enableViewState="false" />
d.对网站服务器的所有网站程序都禁用ViewState,在Machine.config 中,修改<pages>元素如下所示:
<pages enableViewState="false" />
3)确定你的ViewState大小。
启用页面的tracing 功能,你可以监控每一个控件ViewState的大小。你可以根据这些信息,决定优化ViewState的大小;或者决定哪些控件的ViewState需要禁用。