为什么要写篇文章
谈到ASP.NET应用的开发,使我不禁想起之前有朋友对我说过的一句话:做网站没有任何的技术含量。后来他告诉我,做网站,在.NET平台上面很简单,不就是拖几个控件,搞点布局,写点js,然后敲上几个数据的增删查改就完了,系统大了,就多敲几个。当时,朋友之所以说这样的话,是与他的公司与项目背景相关的。
在很多的外包公司里面,常常用ASP.NET来快速的搭建一个Web应用,例如OA系统,企业门户,管理系统,而这些系统往往都注重在业务流程上面,不会在其他方面关注过多,例如,性能,使用这些系统的用户也不多,顶多几千个,所以对于很多真正触及到Web应用的要考虑的问题,例如,高并发,高性能,稳定,安全等,没有接触到。后来,我去了其他的公司,接触到那种承受百万,千万级访问量的应用的时候,越发觉得自己有很多的知识需要学习。
在与朋友共事的一些项目中,很多项目的性能都很差,我们大家都想解决这个问题,但是都没有办法,仅仅只是知道一些基本的措施,很多都是从网络上面“道听途说”,例如用stringbuilder来拼接字符串,尽量用for而不是foreach。其实说到底,还是我们对.NET不够深入,虽然说,我们在.NET平台上面做了很多的项目,其实很多的应用只是在.NET平台的表层开发。(由此可见,“题海战术”不一定能够练就解题高手,也不一定能够练就解决问题的思维。)
其实性能优化问题,不仅仅只是Web应用独有的,而是说,在Web应用中,可能关注的多一点。本篇文章谈的是ASP.NET应用的性能优化,其实,从本质上面,还是谈的.NET应用的优化。对于其他平台的朋友,也是非常有参考价值的。
在本篇文章中,不会谈及很多的调优的方法理论(其实这些方法论是很有作用的),我会从谈及一些实际,可操作性的知识,让朋友们学而即用,同时也让朋友对开始对.NET加深认识。
本篇的内容从以下几个方面进行展开:内存瓶颈分析,CPU瓶颈分析,缓存分析,资源等待分析,数据库瓶颈分析,HTTP优化。
首先来看看内存瓶颈分析。虽然,我在之前的一篇稿子《.NET企业级开发》中谈 这个问题,但是,为了本篇文章的完整性,我还是提一下,同时也将这个问题讲更全面一些。
内存瓶颈分析
内存性能问题可以分为两个部分:内部内存压力,外部内存压力。其中内部内存压力主要是站点本身在运行的过程中消耗过多的内存,基本是可以从托管资源,非托管资源两方面分析;而外部内存压力指代站点所在的服务器上面的其他应用于站点本身之间进行资源的争夺,从而使得站点可以使用的内存太少。那么在ASP.NET企业级应用中,我们技术人员关注点可以放在内部内存压力。
首先看看托管资源的问题。
为什么要讨论托管资源?因为托管资源(就是分配中在托管堆上面的对象),分配在托管堆上,而托管堆在内存中,所有托管资源的合理的分配和回收,会对内存产生影响。
ASP.NET应用的功能就是由很多的对象组合完成的,所以讨论托管资源很有必要。
在.NET中,托管堆分为两类:大对象托管堆,小对象托管堆。一般而言,如果对象所占的空间小于85K,就分配在小堆上面,反之,分配在大堆上面。如图的小堆图:
在对上面,对象被划分为三代:0,1,2代。“代”数越大,被回收的可能性就越小。基于这个理论,就要避免原本只要是低代的对象变为高代的对象,例如某个对象用完之后就销毁的,原本是0代的,现在存活到了2代,那么它所占的内存就浪费了。虽然,垃圾回收机制没有在一定程度上回收,但是如果我们总是“霸占”着对象,垃圾回收也没有办法。
下面,举个例子,形象的说明一下。对于一个大型的ASP.NET应用而言,里面会包含很多的对象,假设10000个,其中每次请求都要产生的100个临时对象。如果这些临时对象,被不合理的分配,成为了大代的对象,我们来算一算。
如果这个100个对象每个占1k的空间,那么100个,我们约等于0.1M,如果站点访问量是10w,那么如果这些0.1乘以10w,如果访问量是100w,1000w,结果如何?大家已经清楚了。很多,需要将问题放大来看,结果就很清晰了。
对于对象的使用,有一点要记住:尽可能迟的分配,尽可能早的释放。
下面,我们可以谈谈,如何找出内存问题。
可以采用工具加分析的方式。可以采用System Counter,CLR Profiler,ANTS Memory Profiler(Red Gate)等。其中System Counter,CLR Profiler分析的比较的粗糙,ANTS Memory Profiler(Red Gate)可以指出是哪段代码有问题,方便解决问题。如图
本篇由于篇幅的限制,先到这里,下一篇,我们可以看看一些常见的性能问题,例如字符串相关问题,Session,缓存,对象池。