• 转 内存不断上升处理方法


    http://www.livelycity.com/Blog/Longzx/2004_10_17_longzx_archive.html

    过2天的跟踪确认,发布服务的内存泄漏问题彻底解决了,总结这次故障排除过程,可以说是一波三折。

    10月4日大蜘蛛上线后,我就隐约感到内存消耗不正常,当时没太在意,接下来连续几天,早上一起来,就发现任务管理器中的内存使用量达到了1300M,才开始到网上找资料,开始艰苦的故障排除过程。

    网上找技术资料,Baidu是帮不上什么忙的,google的网页搜索用处也不大,google的网上论坛搜索不错,但经常不能用,好在还有一个google groups2,msdn也能辅助用用,断断续续找到一些类似的问题,在.net环境下,使用内存不断的增加,但回答一般认为是因为没有释放资源、或者是判断错误、并坚信.net不存在内存泄漏问题。

    问的人还是很多,其中有好些同时提到在项目中用到了ThreadPool,我对ThreadPool以前了解比较少,所以也认为可能是那里出了问题,所以自己重新编了一个ExThreadPool来替代,第二天发现仍然如此(因为内存是缓慢的增加,测试非常花时间,有时需要测试好几次才能确认,辛苦啊。),后来干脆不用线程池,故障依旧!不用多线程,故障依旧!单独测试新增的部分,确认内存泄漏就发生在与下载网页相关的部分。

    专门搜索下载网页和内存泄漏,找到一个完全类似的search/indexing应用,故障的描述完全一样,可惜没有解答。

    后来不知怎么找到一个关于LOH(Large Object Heap)的帖子,里面提到超过.net会把超过85k的对象放在一个区域单独管理,这个区域只增加,不会缩小,但可以重用,于是我限制所有可能出现大对象的地方,好像解决了,很长时间内存都没有增加多少。但第二天早上一看,故障依旧!(后来确认这个bug在clr1.1中已经修复。)

    接连遭受挫折后,心情有点沮丧,甚至怀疑选择.net一开始就是个错误。网上有人提示使用windbg把内存导出来看看到底什么东西占用了内存。

    我对这种底层的调试工具一向抱有敬而远之的态度,但没办法,这差不多是唯一的救命稻草。在寻找windbg的过程中,看到微软官方关于asp.net的内存调试指南,看上去很复杂,但硬着头皮一步一步调试下来,收获很大,发现windbg是非常强大的调试工具,也了解了任务管理器中的使用内存和虚拟内存的区别,对性能查看器也有了更深入的了解。

    出乎我的意外,内存堆中并没有大量的LOH对象,不过提示虚拟内存碎片很多,再去搜索关于.net虚拟内存碎片的文章,终于在一个微软雇员的blog中找到了一篇详细描述虚拟内存碎片的产生机理的文章,虚拟内存碎片主要由pinned对象造成,只有在vs2005.net中才可能在clr中解决,在切换到vs2005.net之前,能够做的就是:
    1。减少pinned对象的创建。
    2。尽量同时创建pinned对象。
    3。缩短pinned对象的生命期。

    通过windbg发现,pinned对象主要是http连接的通讯缓存对象。我采用第三种办法,增加了一段代码 myHttpWebRequest.KeepAlive=false; 如果http连接不是持久的,在网页下载结束后,缓存对象立即就可以被GC回收,出现虚拟内存碎片的概率也就降低了。

    修改后,内存奇迹般的不增加,保持在一个很低的水平,2天过去了,一直很好。这使我想起那个“一线万金”的典故了:
    1923年,福特公司有一台大型电机发生故障,全公司所有工程师会诊两三个月没有结果,邀请斯泰因梅茨诊断。他在这台大型电机旁边搭了帐篷,整整检查了两昼夜,仔细听着电机发出的声音,反复进行各种计算,最后用梯子上上下下测量了一番,就用粉笔在这台电机的某处画线做了记号,对福特公司的经理说:“打开电机,把做记号地方的线圈减少16圈,故障就可排除。”工程师们半信半疑地照办了,结果电机正常运转,大家为之一惊。
    事后,斯泰因梅茨向福特公司要一万美金作为报酬。有人嫉妒说:“画一根线索要一万美金,这是勒索。”斯泰因梅茨听后一笑,提笔在付款单上写道:“用粉笔画一条线,一美元;知道在哪里划线,9999美元!”


    2004-10-19
     
    增加一行代码。
    myHttpWebRequest.KeepAlive=false;
    内存碎片问题基本解决,不建立持久http连接,pinned通信缓存对象的生命期比较短,更快被gc回收,导致.net内存堆形成large free block的概率变小,内存溢出的概率也就少了。

    2004-10-18
     
    OutOfMemoryException and Pinning 才是内存耗尽的真正原因,首次使用windbg/adplus/sos等调试工具。

     
    .net中的LOH(Large Object Heap)害人不浅,你如果频繁的创建大于85k的大对象,比如用string表示的文本文档,就会感觉出现了内存泄漏,应用程序占用的内存一个劲儿往上升,直到出现out of memory为止。
    我也是好不容易才在网上找到一点蛛丝马迹微软自己的文档也稍微提到这个问题。
    开始怀疑ThreadPool,后来怀疑多线程不安全,现在怀疑LOH,做了无数次冗长的测试(有谁知道我的痛苦?),真的希望这一次能够搞定。

  • 相关阅读:
    美国大学排名之本科中最用功的学校top15
    PhpStorm (强大的PHP开发环境)2017.3.2 附注册方法
    获取地址栏的URL: PHP JS
    怎么给php下拉框默认选中
    在JS中使用全局变量
    原生和jQuery的ajax用法
    XAMPP重要文件目录及配置
    select获取下拉框的值 下拉框默认选中
    h5 时间控件问题,怎么设置type =datetime-local 的值
    JS截取字符串常用方法详细整理
  • 原文地址:https://www.cnblogs.com/flyfish/p/331602.html
Copyright © 2020-2023  润新知