对于WEB程序来说,它寄宿在IIS提供的w3wp进程中,这个进程占用的内存大小和你的应用程序的使用有个直接关系,你的程序写的标准,它占用内存就相对低,你的程序写的伪范规,该释放的东西不让系统释放(有些对象GC回收不了),就会造成内存使用过高的情况,对于32位系统来说,最高1.6G,超过后,进程自动挂掉!
对于本地服务来说,一般我们采用windowService,windowform来承载,它会自己有一个进程,而最近,我的windowService占用内存过高的问题真的出现了,不到5分钟,进程已经达到500多兆了,而且还在处理递增长的趋势,当我们review代码后,发现了一个大问题,看下面代码您是否也发现了呢,代码里的坏味道
public class User_SendMessageJob : JobBase, IJob { private static object lockObj = new object(); private object IBigRepository = new object(); public void Execute(IJobExecutionContext context) { lock (lockObj) { #region 需要处理的任务 //Logger.Info(context.JobDetail.Key.Name + DateTime.Now); #endregion } } }
上面的代码,声明了两个全局变量lockObj和IBigRepository,其中这个IBigRepository在方法Execute被调用,并用是轮训调用,为了避免并发冲突,采用了lock进行排它锁的设计,当这个全局对象本应该在程序运行结束后,就被释放,但是,我们去想,如果线程1正在执行lock里的代码,而线程2这种由于轮训服务,也开始进入方法,这时IBigRepository对象没有被释放,线程2又产生了一个新的对象,这时,我们的IBigRepository对象就越来越多,导致你的内存消耗越来越大!
正确的作法应该是,将IBigRepository对象声明在Execute方法里,作为局部变量,当lock结束后,就会被系统自动加收,下一个线程2进来后,才会建立新的IBigRepository对象,这样,我们就保存了,在轮训服务中,始终只有一个IBigRepository对象被建立,这种设计才是正确的.
看一下修改后的代码
public class User_SendMessageJob : JobBase, IJob { private static object lockObj = new object(); public void Execute(IJobExecutionContext context) { lock (lockObj) { object IBigRepository = new object(); #region 需要处理的任务 //Logger.Info(context.JobDetail.Key.Name + DateTime.Now); #endregion } } }
在修改了程序之后,再看一下内存,只有200M,而且没有递增的趋势,这才是正确的程序,所以说,有些基础知识很重要,我们不应该去忽视它,就像老赵说过一句话:学好操作系统才能写出好的windows程序,学习IIS运行机制,才能写出好的WEB程序!
面向服务架构~本地轮训服务占用内存过高的问题