提高系统性能
之ASP.NET
性能是计算机程序的一个重要问题,特别是须要接收大量请求的Web应用程序。一个显著增加性能的方式是购买更快的硬件和更多内存,但是也可以使用很多方法来调整代码,增加性能,并且有些方法效果还十分显著。首先了解一下ASP.NET中能够最大程度改善性能的相关内容,再来看看.NET中一些增强性能的话题。
会话状态(Session State)
会话状态是个很不错的东西,但是不是所有的应用程序或者页面都需要它。对于那些没有禁用它的应用程序,可以通的设定Page指令中的EnableSessionState属性为false,来禁止会话状态,如下面的示例所示:
<% Page Language=”C#” EnableSessionState=”false” %>
如果一个页面没有创建或者修改会话变量,但是还是须要方问它,则可以把会话状态设置成只读
<% Page Language=”C#” EnableSessionState=”ReadOnly” %>
默认情况下,Web服务不允许会话状态。只有当WebMethod特性的EnableSession属性为true时,才可以访问会话状态:
[WebMethod(EnableSession=true)]
通过编辑应用程序的Web.config文件中的SessionState节,可以禁用整个应用程序的会话状态:
<sessionState mode = “off”>
会话状态可以用三种方式保存
l In-process(进程内)
l Out-of-process(作为windows服务)
l Out-of-process(保存在SQL Server数据库中)
每种方式都有优点和缺点。在进程内存储会话状态是最快的,但是需要消耗内存;使用SQL Server数据库保存,速度最慢,但是它可以获得持久化的保存,可靠性最高,而且可以无限扩展Session的容量;作为Windows服务时,也是在内存中保存,但是它可以部署在web服务器以外的服务器上,这样可以取得介于其它两种方式之间的性能。
视图状态(View State)
自动视图状态管理是ASP.NET服务器控件的另一个很好的特性,它可以让控件在一次关联搜索之后显示当前的属性值,但是不需要程序员做任何工作,然而它会给性能带来损失。该信息通过一个隐藏控件来回传的,这一传递消耗带宽,并需要时间来处理。你可以通过设置一个GridView的ViewState属性来查看数据量的不同。对于一个有20行的GridView来说,ViewState = true 可能会增加几K的数据量。所有我强烈推荐,在所有的ASP.NET查询页面中禁止GridView的ViewState。 默认情况下所有的服务器控件都允许视图状态,为禁用一个服务器的控件视图状态,可以使用EnableViewState属性设为false,如下图所示:
<asp:TextBox id=”txtBookName” text =”book name” EnableViewState=”false” runat=”server”>
通过设置Page指令的EnableViewState属性为false,可以禁用整个页面的视图状态:
<%@ Page Language=”C#” EnableViewState =”false” %>
缓存
只要可以使用输出和数据缓存,就应该使用它们。缓存对于那些须返回相对静止的数据或者限制查询参数范围的数据查询意义重大,高效使用缓存可以有效的改善网站的性能。ASP.NET2.0中的缓存技术主要有三种
l 输出缓存
页面缓存,对于第一次访问的URL进内存存储(所有请在查询页面使用Get 方法,而不是Post方法)。
l 数据缓存
对第一次数据查询进行指定时间内的内存存储,以提高数据库访问性能(只对SQL Server有效)
l 对象缓存
在ASP.NET中,我们可以把任何需要缓存的对象,存储至内存中。(语法Cache[“key”] = object.)
关于缓存的使用,是一个比较复杂的话题,这里不再详细说明。
服务器控件
服务器控件很方便,且有很多优点。尽管如此,它们也是消耗一定的资源。有时候并非最适合使用的控件类型。
通常,如果无须用编程方式修改一个控件,那么一要使用一个简单的服务器控件,而是使用一个传统HTML控件。举个例子,如果在页面上放置一个简单的标签,就不需要使用服务器控件,除非须要读取或者更改Label控件的Text属性值。
尽可能的消除异常
使用try…catch块可以控制程序流。然而,该编码技术是性能的关键瓶颈。如果在一开始先测试条件是否不成立,如果条件满足,则对它进行处理,这样就可以做得更好。
例如,不要把两个数相除放在try…catch块中,捕获抛出的除零异常,而是先测试除数是不是0,如果是,不要做任何操作。类似的,虽然只有几次不可避免的情况,但是抛出自已创建的异常也是很耗费资源的。
ASP.NET2.0为了使程序避免使用try…catch,在Web.config 加入了“错误页面”的配置节。方法如下:
<System.Web>
…
.<customErrors
defaultRedirect=”CustomErrorPage.htm”
. mode=”RemoteOnly”
<error statusCode=”400” redirect=”Customerrorpage400.htm”>
<error statusCode=”500” redirect=”Customerrorpage500.htm”>
<error statusCode=”600” redirect=”Customerrorpage600.htm”>
…
<System.Web>
其中mode 属性为“off”时,不跳转到Error页面;“On”时表示跳转并显示Error页面;“RemoteOnly”表示只在本机显示错误详细信息,而远程用户只能看到Error页面。
另外,如果我们希望在Error页面上显示一些和错误相关内容,可以在global.asax文件中的Application_OnError事件处理程序中添加代码,而不是到处使用try…catch。下面的代码是毫无意义、降低性能的最好办法:
try
{
}
catch (Exception err)
{
throw err;
}
字符串拼接
字符串在.NET Framework中是不可变的。这意味着看上去改变字符串的方法和操作,实际上是返回了一个修改过的string复件。这会有很严重的性能问题。如果正在进行字符串修改,请一定要使用StringBuilder类。让我们来做个实验:用两种不同的方法计算10,000个字符串创建一个字符串的时间。
1、使用简单的字串拼接:
for (int i=0; i< 10000;i++)
{
strSub= i.ToString();
strWhole = strWhole + “ ” + strSub;
}
2、使用StringBuild 实现
StringBuilder sb = new StringBuilder();
for (int i=0; i< 10000;i++)
{
strSub= i.ToString();
sb.Append(“ ”);
sb.Append(strSub);
}
在我的机器上的测试结果是StringBuilder比字符串简单的拼接的方法快300多倍。你可以在自己的机器上测试出结果。
不使用后期绑定
.NET语言允许前期和后期绑定。前期绑定在编译时被已经进行过类型处理。后期绑定是用反射实现的,虽然很方便,但是速度要慢的多。例如对接口参数的类型进行抽象,就是一个典型的后期绑定。
禁用调试模式
这个很简单,但是许多人不注意,把Debug版本的程序发布出去。Debug版本的dll记录的大量的调试信息和反射机制。请发布你的程序时一定要把项目设置为Release版本。
使用存储过程
当与数据库交互时,使用存储过程总比传入命令字符串要快很多。这是因为存储过程是通过数据库引擎编译和优化的。在任何可能的情况下,都应该使用存储过程(引自:《Programming ASP.NET》 Jesse Liberty, Dan Hurwitz美国)
使用DataReader类
有两种主要的从数据库获得数据的方式:从一个DataReader对象获得,或者从一个DataSet对象获得。如果只是需要向前的数据流,那么DataReader类是更快的数据库访问方式,请在所有的查询页面中使用它。
不要使用OleDB类
一些数据库引擎有专门设计好的托管类用于与数据库交互,使用这样的类要比使用OleDB类好的多。