• asp.net 优化一


    三、c#(或vb.net)程序改进


    1、使用值类型的ToString方法

      在连接字符串时,经常使用"+"号直接将数字添加到字符串中。这种方法虽然简单,也可以得到正确结果,但是由于涉及到不同的数据类型,数字需要通过装箱操作转化为引用类型才可以添加到字符串中。但是装箱操作对性能影响较大,因为在进行这类处理时,将在托管堆中分配一个新的对象,原有的值复制到新创建的对象中。

      使用值类型的ToString方法可以避免装箱操作,从而提高应用程序性能。

    int num=1;
    string str="go"+num.ToString();


    2、运用StringBuilder类

      String类对象是不可改变的,对于String对象的重新赋值在本质上是重新创建了一个String对象并将新值赋予该对象,其方法ToString对性能的提高并非很显著。

      在处理字符串时,最好使用StringBuilder类,其.NET 命名空间是System.Text。该类并非创建新的对象,而是通过Append,Remove,Insert等方法直接对字符串进行操作,通过ToString方法返回操作结果。

      其定义及操作语句如下所示:

    int num;

    System.Text.StringBuilder str = new System.Text.StringBuilder(); //创建字符串

    str.Append(num.ToString()); //添加数值num

    Response.Write(str.ToString); //显示操作结果


    3、使用 HttpServerUtility.Transfer 方法在同一应用程序的页面间重定向

      采用 Server.Transfer 语法,在页面中使用该方法可避免不必要的客户端重定向(Response.Redirect)。

    4、避免使用ArrayList。

    因为任何对象添加到ArrayList都要封箱为System.Object类型,从ArrayList取出数据时,要拆箱回实际的类型。建议使用自定义的集合类型代替ArrayList。asp.net 2.0提供了一个新的类型,叫泛型,这是一个强类型,使用泛型集合就可以避免了封箱和拆箱的发生,提高了性能。

    5、使用HashTale代替其他字典集合类型
    (如StringDictionary,NameValueCollection,HybridCollection),存放少量数据的时候可以使用HashTable.

    6、为字符串容器声明常量,不要直接把字符封装在双引号" "里面。
    //避免
    MyObject obj = new MyObject();
    obj.Status = "ACTIVE";

    //推荐
    const string C_STATUS = "ACTIVE";
    MyObject obj = new MyObject();
    obj.Status = C_STATUS;

    7、不要用ToUpper(),ToLower()转换字符串进行比较,用String.Compare代替,它可以忽略大小写进行比较.
    例:
    const string C_VALUE = "COMPARE";
    if (String.Compare(sVariable, C_VALUE, true) == 0)
    {
    Console.Write( "相同");
    }
    也可以用str == String.Empty或者str.Length == 0判断是否为空。(注意判断输入数据的长度,可防止sql注入式攻击)
    将String对象的Length属性与0比较是最快的方法,避免不必要的调用 ToUpper 或 ToLower 方法。

    8、类型转化Int32.TryParse()优于Int32.Parse()优于Convert.ToInt32()。

    建议.NET1.1下用Int32.Parse();.NET2.0用Int32.TryParse()。
    因为:
    Convert.ToInt32 会把最终的解析工作代理给 Int32.Parse;
    Int32.Parse 会把最终的解析工作代理给Number.ParseInt32;
    Int32.TryParse 会把最终的解析工作代理给Number.TryParseInt32。

    9、如果只是从XML对象读取数据,用只读的XPathDocument代替XMLDocument,可以提高性能

    //避免
    XmlDocument xmld = new XmlDocument();
    xmld.LoadXml(sXML);
    txtName.Text = xmld.SelectSingleNode( "/packet/child").InnerText;

    //推荐
    XPathDocument xmldContext = new XPathDocument(new StringReader(oContext.Value));
    XPathNavigator xnav = xmldContext.CreateNavigator();
    XPathNodeIterator xpNodeIter = xnav.Select( "packet/child");
    iCount = xpNodeIter.Count;
    xpNodeIter = xnav.SelectDescendants(XPathNodeType.Element, false);
    while(xpNodeIter.MoveNext())
    {
    sCurrValues += xpNodeIter.Current.Value+ ",";
    }


    10、避免在循环体里声明变量,应该在循环体外声明变量,在循环体里初始化。

    C#程序开发要遵循的一个基本原则就是避免不必要的对象创建

    //避免
    for(int i=0; i<10; i++)
    {
    SomeClass objSC = new SomeClass();
    }

    //推荐
    SomeClass objSC = null;
    for(int i=0; i <10; i++)
    {
    objSC = new SomeClass();
    }

    11、捕获指定的异常,不要使用通用的System.Exception.

    //避免
    try
    {
    <some logic>
    }
    catch(Exception exc)
    {
    <Error handling>
    }

    //推荐
    try
    {
    <some logic>
    }
    catch(System.NullReferenceException exc)
    {
    <Error handling>
    }
    catch(System.ArgumentOutOfRangeException exc)
    {
    <Error handling>
    }
    catch(System.InvalidCastException exc)
    {
    <Error handling>
    }

    12、使用Try...catch...finally时, 要在finally里释放占用的资源如连接,文件流等
    不然在Catch到错误后占用的资源不能释放。

    try
    {}
    catch
    {}
    finally
    {
    conntion.close();
    }

    13、不要用Exception控制程序流程
    有些程序员可能会使用异常来实现一些流程控制。例如:

    try{
    result=100/num;
    }
    Catch(Exception e)
    {
    result=0;
    }

    但实际上,Exception是非常消耗系统性能的。除非必要,不应当使用异常控制来实现程序流程。上面的代码应当写为:

    if(num!=0)
    result=100/num;
    else
    result=0;


    14、避免使用递归调用和嵌套循环,使用他们会严重影响性能,在不得不用的时候才使用。

    15、禁用VB.net和Jscript动态数据类型

    应当始终显示地申明变量数据类型,这能够节约程序的执行时间。以往,开发人员喜欢使用 Visual Basic、VBScript 和 JScript 的原因之一就是它们所谓“无类型”的性质。变量不需要显式类型声明,并能够简单地通过使用来创建它们。当从一个类型到另一个类型进行分配时,转换将自动执行。不过,这种便利会大大损害应用程序的性能。
    如:
    为了获得最佳的性能,当声明 JScript .NET 变量时,请为其分配一个类型。例如,var A : String;


    四、使用缓存

    1、使用Output Cache缓存数据

    提供缓存功能是ASP.net中非常强大的一种功能。曾看到过某些评测说:ASP.net程序的性能比SUN的JSP应用程序性能快上几倍,实际上,该评测程序非常重要的一点就是使用了很多ASP.net的缓存功能。

      如果你的组件是要在Asp.net应用程序中运行,你只要把System.Web.dll引用到你的项目中就可以了。然后用HttpRuntime.Cache属性就可访问Cache了(也可以通过Page.Cache或HttpContext.Cache访问)。

      有以下几条缓存数据的规则。第一,数据可能会被频繁的被使用,这种数据可以缓存。第二,数据的访问频率非常高,或者一个数据的访问频率不高,但是它的生存周期很长,这样的数据最好也缓存起来。第三是一个常常被忽略的问题,有时候我们缓存了太多数据,通常在一台X86的机子上,如果你要缓存的数据超过800M的话,就会出现内存溢出的错误。所以说缓存是有限的。换名话说,你应该估计缓存集的大小,把缓存集的大小限制在10以内,否则它可能会出问题。在Asp.net中,如果缓存过大的话也会报内存溢出错误,特别是如果缓存大的DataSet对象的时候。

      这里有几个你必须了解的重要的缓存机制。首先是缓存实现了“最近使用”原则( a least-recently-used algorithm),当缓存少的时候,它会自动的强制清除那些无用的缓存。其次 “条件依赖”强制清除原则(expiration dependencies),条件可以是时间,关键字和文件。以时间作为条件是最常用的。在asp.net2.0中增加一更强的条件,就是数据库条件。当数据库中的数据发生变化时,就会强制清除缓存。

      使用 ASP.NET 缓存机制有两点需要注意。首先,不要缓存太多项。缓存每个项均有开销,特别是在内存使用方面。不要缓存容易重新计算和很少使用的项。其次,给缓存的项分配的有效期不要太短。很快到期的项会导致缓存中不必要的周转,并且经常导致更多的代码清除和垃圾回收工作。若关心此问题,请监视与 ASP.NET Applications 性能对象关联的 Cache Total Turnover Rate 性能计数器。高周转率可能说明存在问题,特别是当项在到期前被移除时。这也称作内存压力。

    切记:

    应该:
    应该缓存那些经常被访问、同时变化频率不大的数据
    应该缓存整个应用程序都要使用的设置或对象,但这些设置和对象必须在其生存期内不会变化
    不应该:
    不要缓存个人信息。如果缓存个人信息,其他人很容易取得这些信息。
    不要缓存包含基于时间值的页面,否则浏览者将无法理解为何时间总是滞后。
    不要缓存用户随时都会修改的对象,如购物车。


    ASP.net中常用的缓存方式有:

    1)页面缓存(对整个页面进行缓存)

    <%//Response.AddHeader("Last-Modified", DateTime.Now.AddHours(-1).ToString("r"));%>
    <% Response.AddHeader("Cache-Control", "max-age=86400"); %>
    <%//Response.AddHeader("Date", DateTime.Now.AddMinutes(-59).ToString("r"));%>

    <%@Page OutputCache VaryByParams=”classid;page” Duration=”3600” %>

    .net2.0中为:
    <%@OutputCache VaryByParam=”classid;page” Duration=”3600” %>

    你就可以有效的利用第一次请求里生成的页面输出缓存内容,3600秒后重新生成一道页面内容。这种技术其实也是运用一些低层的Cache API来实现。用页面输出缓存有几个参数可以配置,如上面所说的VaryByParams参数,该参数表示什么时候触发重输出的条件,也可以指定在 Http Get或Http Post 请求模式下缓存输出。

    例如当我们设置该参数为VaryByParams=”classid;page”的时候,default.aspx?classid=3&page=1 请求的输出都会被缓存起来。没有参数,或不用参数时用none。如果传递的参数不止一个,那么即使字符串参数与值都相同,但排列次序不同,那么在请求页面时,也将生成不同的缓存页。例如default.aspx?first=1&last=1 和default.aspx?last=1&first=1虽然参数完全相同,但由于排列次序不同,将生成两个不同的缓存页。


      许多人都没有意识到当用页面输出缓存的时候,asp.net也会生成HTTP头集(HTTP Header)保存在下游的缓存服务器中,这些信息可以用于Microsoft Internet安全性中以及加速服务器的响应速度。当HTTP缓存的头被重置时,请求的内容会被缓在网络资源中,当客户端再次请求该内容时,就不会再从源服务器上获得内容了,而直接从缓存中获得内容。

      虽然用页面输出缓存不提高你的应用程序性能,但是它能减少了从的服务器中加载已缓存页面内容的次数。当然,这仅限于缓存匿名用户可以访问的页面。因为一旦页面被缓存后,就不能再执行授权操作了。


    2)片断缓存(对页面的某一部分,如某个User Control进行缓存)

    <%@ OutputCache Duration="60" VaryByParam=”TextBox1;TextBox2” %>

    在ASP.net中,除了在页面范围内使用缓存,也还可以针对User Control使用Output Cache参数实现对用户控件的缓存。同样的,一个页面中相同类型的控件也可以有多个不同的缓存。可以根据参数来实现不同的缓存。页面缓存和片断缓存可以同时使用。


    3)数据缓存

    数据缓存是一种强大而又非常简单的缓存机制,它可以在缓存区中为每个应用程序保存各种对象,这些对象可以根据http的请求被调用,但是在各个不同的应用程序中这些对象都是私有的。
    数据缓存是通过Cache类来实现的。当应用程序建立时,一个Cache类就同时被建立,缓存实例的生存周期就是应用程序的生存周期,它会随着应用程序的重新运行而重建,通过Cache类的方法,我们可以将数据对象放入缓存区,然后通过关键字匹配寻找并使用这些对象。
    Cache类通过一个借口来控制所有需要缓存的内容,包括规定缓存的时间和缓存方式,可以通过如下方法添加缓存对象:

    Cache[“关键字”] = 关键字的取值;

    然后通过下面的方法来访问这个对象:

    string mKeyValue = “”;
    if(Cache[“关键字”] != null)
    {
    mKeyValue = Cache[“关键字”];
    }

    注意Page.Cache和HttpContext.Current.Cache区别:
    它们指的同一个对象,在Page里,用Page.Cache,如果在global.asax或自己的类里用:HttpContext.Current.Cache,在有些事件中,由于其没有HttpContext,就用HttpRuntime.Cache。


    数据缓存的过期依赖条件

    某种意义上,Cache和Application是一样的,都是一种公有的对象。为了取得缓存与数据有效性之间的平衡,可以根据需要对缓存过期策略进行合理的设置。


    文件依赖
    Cache.Insert (“Mydata”, Source , New CacheDependency(Server.MapPath(“authors.xml”)));
    此代码的含义是当authors.xml文件不发生变化的时候,缓存MyData始终有效。


    时间依赖
    设定1小时后过期,这是一种绝对过期。
    Cache.Insert(“Mydata”,Source,null ,DateTime.Now.AddHours(1),TimeSpan.Zero);


    相对过期依赖
    当DataSet不再发生变化20分钟以后,缓存过期。
    Cache.Insert(“MyData”,Source,null,DateTime.MaxValue,TimeSpan.FromMinutes(20));

    一个示例:

    //绝对过期!!!(用来保存公用的,数据量小的数据对象,可以是任何对象)
    //设置
    if (System.Web.HttpContext.Current.Cache["ok"] == null)
    System.Web.HttpContext.Current.Cache.Insert("ok", "data", null, DateTime.Now.AddSeconds(300),System.Web.Caching.Cache.NoSlidingExpiration);
    //读取
    if(System.Web.HttpContext.Current.Cache["ok"]!=null)
    this.Response.Write(Convert.ToString(System.Web.HttpContext.Current.Cache.Get("ok")));

    最后要注意:
    在Web Form调试期间不能使用缓存,否则你对页面所做的修改在缓存过期之前不会得到显式加载。正确的做法应该是在调试结束之后,给需要放入缓存的页面、用户控件或对象加上缓存指令。最后建立部署和安装项目,生成安装数据包,这时候就可以到服务器上去发布你的产品了。

    详细参考:
    http://hi.baidu.com/erics_lele/blog/item/674e46e7622f262cb83820c6.html
    .net/chengking/archive/2005/10/03/494545.aspx" target="_blank">http://blog.csdn.net/chengking/archive/2005/10/03/494545.aspx


    2、预请求缓存

      虽然Cache API设计成用来保存某段时间的数据,而预请求缓存只是保存某个时期的某个请求的内容。如果某个请求的访问频率高,而且这个请求只需要提取,应用,修改或者更新数据一次。那么就可以预缓存该请求。我们举个例子来说明。

      在CS的论坛应用程序中,每一个页面的服务器控件都要求得到用于决定它的皮肤(skin)的自定义的数据,以决定用哪个样式表及其它的一些个性化的东西。这里面的某些数据可能要长时间的保存,有些时间则不然,如控件的skin数据,它只需要应用一次,而后就可以一直使用。

      要实现预请求缓存,用Asp.net 的HttpContext类,HttpContext类的实例在每一个请求中创建,在请求期间的任何地方都可以通过HttpContext.Current属性访问。HttpContext类有一个Items集合属性,在请求期间所有的对象和数据都被添加到这个集合中缓存起来。和你用Cache缓存访问频率高数据一样,你可以用HttpContext.Items缓存那些每个请求都要用到的基础数据。它背后的逻辑很简单:我们向HttpContext.Items中添加一个数据,然后再从它里面读出数据。
  • 相关阅读:
    hdu--2852--树状数组
    hdu--2848--未解决
    二进制与十进制之间蛮好的转换方式
    hdu--2846--字典树<怪我思维不够跳跃>
    hdu--2845--dp
    hdu--2844--多重背包
    hdu--1789--贪心||优先队列
    hdu--1978--记忆化深度搜索||递推
    hdu--2830--任意交换列的矩阵
    hdu--1506--矩阵求和<stack>
  • 原文地址:https://www.cnblogs.com/chjf2008/p/1278039.html
Copyright © 2020-2023  润新知