Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GC算法和IE中JS内存泄露

Avatar for xwcoder xwcoder
December 06, 2012

 GC算法和IE中JS内存泄露

09、10年用ExtJS1.1做OPOA时整理的一份关于内存泄露的文档。现整理成PPT。

Avatar for xwcoder

xwcoder

December 06, 2012
Tweet

Other Decks in Technology

Transcript

  1. 三大传统算法:Reference Counting (引用计数) obj v1 v2 v3 count: 3 循环引用问题

    (从前有座山,山上有座庙,庙里有个老和尚, 老和尚在给小和尚讲故事,讲的啥? 从前有座山,山上有座庙…)
  2. 三大传统算法:Mark-Sweep (标记-清除) Step:1 V1 Q:被使用吗 A: yes, 标记为1 V2 Q:被使用吗

    A: yes, 标记为1 V3 Q:被使用吗 A: no … Q:被使用吗 A: yes Step:2 V1 V2 V3 未被标记,回 收 … 未被标记,回 收
  3. 三大传统算法: Copying (复制) 运行 obj1 obj2 obj3 obj4 using using

    using GC时 obj1 obj2 obj3 obj4 using using using GC后 obj1 obj2 obj3 obj4 using using using
  4. Mark-Compact (标记-整理) step 1: 标记被使用的对象 step 2: 未标记对象和标记对象向相反方向移动 step 3:

    释放未标记对象 • 没有内存浪费 • 效率不错 • 没有内存碎片 结合Mark-Sweep and Copying
  5. Incremental Collecting (增量收集) 基于Mark-Sweep and Copying 实时性较好 M.L.Minsky D.E.Knuth 做了早起研究

    G.L.Steele 1975 Multiprocessing compactifying garbage collection (多进程整理垃圾收集) H.G.Baker 1978 List Processing in Real Time on a Serial Computer (串行计算机上的实时表处理技术) 阐述了多进程环境下的增量收集算法
  6. 那些使用垃圾回收的语言 * 1960 lisp * 1964 Simula * 1969 Smalltalk

    * 1970 Prolog * 1973 ML * 1975 Scheme * 1983 Modula-3 * 1986 Eiffel * 1987 Haskell ...... * java, .net, javascript ......
  7. 浏览器JS引擎GC算法现状 • 截止2008 所有现代浏览器使用Mark-Sweep, even IE • IE <= 8

    BOM and DOM are COM, COM使用引用计数 • IE9 makes BOM and DOM objects into true JS object IE: window.!CollectGarbage() Opera (>=7): window.opera.collect()
  8. 浏览器JS引擎 GC算法现状 • 截止2008 所有现代浏览器使用Mark-Sweep, even IE • IE <=

    8 BOM and DOM are COM, COM使用引用计数 • IE9 makes BOM and DOM objects into true JS object IE: window.!CollectGarbage() Opera (>=7): window.opera.collect()
  9. 何时执行GC IE6 一组阀值: { 256个变量 4096个对象或数组 64K string } 达到其一就执行GC

    IE7 默认阀值 同IE6 GC回收率 < 15%,defalut * 2 GC回收率 > 85%,default还原
  10. ExtJS1.1 中事件造成的泄露问题 Memory Leak is an important thing, especially in

    OPOA especially in OPOA especially in OPOA especially in OPOA
  11. 事件绑定 step 1:Ext.EventManager.on step 2:Ext.lib.Event.on 1. 将fn包装得到h 2. 将h放到fn的属性中 3.

    将h包装得到wrappendFn 4. 将h、wrapFn存储在静态变量 5. 将wrappendFn绑定到el ExtJS1.1 中事件造成的泄露问题
  12. 事件移除 Element.removeListener Element.removeListener( fn ) //原始fn 1. 从fn的_handlers中删除h的引用 2. 对h调用

    Ext.lib.Event.removeListener Ext.lib.Event.removeListener 1. 找到缓存在listeners中的数据 2. 从listeners将缓存删除 ExtJS1.1 中事件造成的泄露问题
  13. 事件移除 Element.removeListener Element.removeListener( fn ) //原始fn 1. 从fn的_handlers中删除h的引用 2. 对h调用

    Ext.lib.Event.removeListener Ext.lib.Event.removeListener 1. 找到缓存在listeners中的数据 2. 从listeners将缓存删除 ExtJS1.1 中事件造成的泄露问题
  14. 事件移除 Element.removeAllListener Element.removeAllListener 1. 取得el上的所有listener 2. 对每一个事件函数调用 removeListener this.getListeners( el,

    eventName );//bug 1. 从listenrs中获得el绑定的h 2. 对h调用 Ext.lib.Event.removeListener ExtJS1.1 中事件造成的泄露问题
  15. this.getListeners( el, eventName );//bug 相比removeListener少做了件事情:没有删除掉fn上缓存的h 后果:fn引用h, h引用el 事件移除 Element.removeAllListener ExtJS1.1

    中事件造成的泄露问题 1. 取得el上的所有listener 2. 对每一个事件函数调用 removeListener • IE6下造成泄漏 • fn为非local变量时 el不会销毁
  16. 解决方案 1. 事件绑定时缓存fn 2. 升级到高版本:ExtJS2.2中解决了该问题 ExtJS1.1组件销毁时没有对生成的所有元素做销毁——逐个打补丁 this.getListeners( el, eventName );//bug

    事件移除 Element.removeAllListener ExtJS1.1 中事件造成的泄露问题 1. 取得el上的所有listener 2. 对每一个事件函数调用 removeListener