2008-03-20
Ext的destroy机制引起的内存问题的分析( 二 )
前几天讨论了一下 ext的 Destroy机制引起的内存问题 发现出现问题的核心点 是 element.removeAllListeners 方法. 相关讨论见:
Ext2.02事件机制缺陷分析,以及解决方案
http://fins.javaeye.com/blog/173818
EXT的destroy方法是不是存在漏洞?
http://fins.javaeye.com/blog/173218
测试使用工具见
http://fins.javaeye.com/blog/172891
解决这一问题后我们可以发现, 依然存在内存无法释放的问题.
分析后得出ext的又一个重大缺陷
还是拿一个最最简单的window做例子
一个干净的页面, 生成上面那个窗口,然后再关闭, 用sIEve查看, 会发现存在很多无法被释放的 ext生成的孤立节点
大家可以注意看一下那些节点的 class ,可以发现如下两个(还有更多,我只是拿他们举例子).
x-dlg-focus x-window-bwrap
也就是说,这两个节点没有被正确的销毁. 跟踪代码可以发现
这两个节点分别对应 window对象的
this.focusEl
this.bwrap
为什么没有被正确的删除呢? 继续跟踪 跟踪所有 window层次结构上的所有类的
destroy beforeDestroy onDestroy 方法
可以看到 ,从来没有显示的调用过 消除他们的方法.
看来我们需要自己手动来销毁他们了.
于是可以修改 Window 的 beforeDestroy 方法:
测试后发现, 依然无法删除那两个节点. 不死心, 继续!!!
再修改
注意 由于 this.bwrap 是window从panel里继承来的, 所以this.bwrap其实应该通过修改panel的代码来消除
我在这里用偷懒的方式 是为了可以用尽量简短的代码来说明问题
再测试, ok 那两个节点没了!!
=================================
综上所述,我们可以得到如下结论:
Ext的作者为各个组件提供的 destroy方法存在严重缺陷.
缺少对一些元素必要的 销毁动作, 同时 没有对属性赋值为 null ,使得浏览器无法回收多余的节点.
页面越复杂 这个问题越严重.
解决办法只能是一个个组件看 看看哪些地方有遗漏 然后进行修补.能在基类中修补尽量修补.
同时 应该为组件增加 afterDestroy方法, 在里面对必要的属性进行赋值为null的操作.
Ext2.02事件机制缺陷分析,以及解决方案
http://fins.javaeye.com/blog/173818
EXT的destroy方法是不是存在漏洞?
http://fins.javaeye.com/blog/173218
测试使用工具见
http://fins.javaeye.com/blog/172891
解决这一问题后我们可以发现, 依然存在内存无法释放的问题.
分析后得出ext的又一个重大缺陷
还是拿一个最最简单的window做例子
win=new Ext.Window({title:" 窗口 ",
width:400,
draggable : false,
shadow : false,
resizable : false,
shim :false,
autoDestroy : true,
height:300});
一个干净的页面, 生成上面那个窗口,然后再关闭, 用sIEve查看, 会发现存在很多无法被释放的 ext生成的孤立节点
大家可以注意看一下那些节点的 class ,可以发现如下两个(还有更多,我只是拿他们举例子).
x-dlg-focus x-window-bwrap
也就是说,这两个节点没有被正确的销毁. 跟踪代码可以发现
这两个节点分别对应 window对象的
this.focusEl
this.bwrap
为什么没有被正确的删除呢? 继续跟踪 跟踪所有 window层次结构上的所有类的
destroy beforeDestroy onDestroy 方法
可以看到 ,从来没有显示的调用过 消除他们的方法.
看来我们需要自己手动来销毁他们了.
于是可以修改 Window 的 beforeDestroy 方法:
Ext.Window.prototype.beforeDestroy = function(){
Ext.destroy(
this.focusEl, // 新增
this.bwrap, // 新增
this.resizer,
this.dd,
this.proxy,
this.mask
);
Ext.Window.superclass.beforeDestroy.call(this);
}
测试后发现, 依然无法删除那两个节点. 不死心, 继续!!!
再修改
Ext.Window.prototype.beforeDestroy = function(){
Ext.destroy(
this.focusEl, // 新增
this.bwrap, // 新增
this.resizer,
this.dd,
this.proxy,
this.mask
);
Ext.Window.superclass.beforeDestroy.call(this);
this.focusEl=null; // 新增
this.bwrap=null; // 新增
}
注意 由于 this.bwrap 是window从panel里继承来的, 所以this.bwrap其实应该通过修改panel的代码来消除
我在这里用偷懒的方式 是为了可以用尽量简短的代码来说明问题
再测试, ok 那两个节点没了!!
=================================
综上所述,我们可以得到如下结论:
Ext的作者为各个组件提供的 destroy方法存在严重缺陷.
缺少对一些元素必要的 销毁动作, 同时 没有对属性赋值为 null ,使得浏览器无法回收多余的节点.
页面越复杂 这个问题越严重.
解决办法只能是一个个组件看 看看哪些地方有遗漏 然后进行修补.能在基类中修补尽量修补.
同时 应该为组件增加 afterDestroy方法, 在里面对必要的属性进行赋值为null的操作.
评论
shumadp.com
2008-07-17
messagebox弹出增加了很多dom,但关闭时内存和dom都毫无变化,打开一看,原来messagebox没有destroy函数。。。晕
csf178
2008-04-29
ext已经够不错了
做到这程度不容易啊
做到这程度不容易啊
felix920
2008-04-29
呵呵,谢谢楼上znjq.
我在整理这些组件的时候才发现你所说的这些问题.
想请教一下,你现在整理那些组件,能否提供一些资料.或者具体一点的解决方案.!
谢谢了!
我在整理这些组件的时候才发现你所说的这些问题.
想请教一下,你现在整理那些组件,能否提供一些资料.或者具体一点的解决方案.!
谢谢了!
znjq
2008-04-29
你查看dom节点的引用数量,会发现很多孤立的节点,这部分节点是不会释放的。
而window本身的泄露又设计到很多其他的组件Element, EventManager,Panel等等,加个destroy方法仅仅是一个临时的处理方法,要根本解决这些泄露问题要fix掉其他组件的bug,window的那些节点是因为被引用而无法释放的.
Ext几乎每个组件在destroy的时候都有内存泄露问题.很多组件的dom在组件destroy根本就没释放绑定事件
举个最简单那的例子Ext.fly就有问题,如果一个组件被destroy掉,而Ext._flyweights还保留着一些dom的引用.
正好最近在做基于ext的opoa的框架,解决了一些组件的bug,等有时间整理一下
而window本身的泄露又设计到很多其他的组件Element, EventManager,Panel等等,加个destroy方法仅仅是一个临时的处理方法,要根本解决这些泄露问题要fix掉其他组件的bug,window的那些节点是因为被引用而无法释放的.
Ext几乎每个组件在destroy的时候都有内存泄露问题.很多组件的dom在组件destroy根本就没释放绑定事件
举个最简单那的例子Ext.fly就有问题,如果一个组件被destroy掉,而Ext._flyweights还保留着一些dom的引用.
正好最近在做基于ext的opoa的框架,解决了一些组件的bug,等有时间整理一下
felix920
2008-04-28
恩,好的。谢谢了。
回头我来试试,不懂的地方在请教你。
回头我来试试,不懂的地方在请教你。
fins
2008-04-28
哦 这个啊 可以重写 window的 destroy方法 删除那些没有被移除的节点
同时 重写 ext的时间注销机制
同时 重写 ext的时间注销机制
felix920
2008-04-28
恩.好的.
多的我就不说了,因为我也是刚学习这东东,
目前的问题:
也是关于ext内存的问题.
我用你介绍的工具测试了一下我现在所做的项目的其中一个页面,并没有发现有内存泄露的节点.
但是我想怎样才能真正达到内存释放的效果呢?因为我现在产生一个window,关闭一个window的时候,内存还是会增加,但是工具里又没有显示有内存泄露的节点。按道理应该会释放掉window打开时所产生的内存啊。
而且我发现改不改基类似乎都没有什么区别,因为在用工具测试的时候两者都不会产生内存泄露节点。
我用的ext2.02。
请指教。
多的我就不说了,因为我也是刚学习这东东,
目前的问题:
也是关于ext内存的问题.
我用你介绍的工具测试了一下我现在所做的项目的其中一个页面,并没有发现有内存泄露的节点.
但是我想怎样才能真正达到内存释放的效果呢?因为我现在产生一个window,关闭一个window的时候,内存还是会增加,但是工具里又没有显示有内存泄露的节点。按道理应该会释放掉window打开时所产生的内存啊。
而且我发现改不改基类似乎都没有什么区别,因为在用工具测试的时候两者都不会产生内存泄露节点。
我用的ext2.02。
请指教。
fins
2008-04-28
ext我也不是很熟 只是凑巧研究了他里面的一些代码
但是对他的认识还不够深
你不妨把问题写出来 让大家一起来帮你
但是对他的认识还不够深
你不妨把问题写出来 让大家一起来帮你
felix920
2008-04-28
fins,你好.!
关于ext2.0我有一些问题想请教你.能否留个联系方式,MSN或者QQ,谢谢了!
关于ext2.0我有一些问题想请教你.能否留个联系方式,MSN或者QQ,谢谢了!
znjq
2008-04-23
panel本身问题就很多。 Panel.js中643行 this.header.unselectable();
查看Element.js 1946行
第一句swallowEvent给header加入了一个事件,但是panel destory的时候并没有释放.
第二句太诡异,加入这句也会导致header节点不释放.
解决办法:
window中也发现很多问题.回头再贴.
猜测很多组件destroy不释放一些dom的绑定事件.
查看Element.js 1946行
this.swallowEvent("selectstart", true);
this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
第一句swallowEvent给header加入了一个事件,但是panel destory的时候并没有释放.
第二句太诡异,加入这句也会导致header节点不释放.
解决办法:
Element.js中unselectable方法注释掉这行
//this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
Panel.js中
beforeDestroy : function(){
if(this.header)this.header.removeAllListeners();
Ext.Element.uncache(
this.header,
this.tbar,
this.bbar,
this.footer,
this.body
);
}
window中也发现很多问题.回头再贴.
猜测很多组件destroy不释放一些dom的绑定事件.
hax
2008-03-23
最好反馈给ext社区。
xfan1982
2008-03-20
这几天看了你的几篇文章,很有收获
gdipkf1986
2008-03-20
呵呵,果然有发现啊,不枉我这几天一直在跟你。呵呵。最近公司的东西就应用到EXT,效率真是要命啊。我就知道Ext内部肯定有问题的。
发表评论
提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则
- 浏览: 743429 次
- 性别:

- 来自: 小胖儿的大城

- 详细资料
搜索本博客
我的相册
customHead
共 76 张
共 76 张
链接
最新评论
-
再发一篇牢骚贴: 文档又丢 ...
文档也是要入CVS的。
-- by bottom -
GT-Grid开发笔记: 这几天 ...
惊鸿逝水 写道>>关于价值,如果GT收费,那么它值多少钱呢? 10元吧 10 ...
-- by lonelyblue -
蝙蝠侠6票房过$2亿之后的 ...
强烈鄙视 剧透的人 尤其是 剧透之前 不写明"剧透 慎入"的人 这电影在我心里 ...
-- by fins -
蝙蝠侠6票房过$2亿之后的 ...
看了。。感想: --BATMAN如果不是有超强的装备,一定是JOKER笑到最后。 ...
-- by dimvar -
GT-Grid "缺陷,、bug、 ...
问题不是出在这 你等着新版本吧 一个属性搞定 :) 今天晚上发布 (前提是 ...
-- by fins






评论排行榜