<<  气质测试结果 | 首 页 | 求两条直线交点坐标  >>
2007-07-07
选择风险

          近期我们在产品前台重构中引入了RIA特性。虽然Ajax比其他RIA技术对于开发人员技术水平的要求较高,开发代价更大,但由于产品特性需要我们仍然采用了Ajax技术,并在众多框架中选择了Prototype(1.5.1)Ext(1.0.1a)组合。在企业级应用开发中做出这样的抉择是需要承担一定的风险的。

 

如期而至的问题

          不出所料,重构工作开展不过两个星期,客户端浏览器的性能问题便凸现出来,使重构进程陷入僵持状态。暂时撇开客户端代码运行速度不说,IE(6 sp2)Fx(2.0.0.4)浏览器出现了不同程度的JavaScript内存泄露,使得客户端浏览器在浏览系统页面一段时间后会消耗大量客户端资源以至浏览器的浏览速度低下甚至瘫痪。使框架问题还是我们编写的客户端代码存在问题呢?我们首先带着这个问题展开了一系列的测试。

         经过初步观察,在系统主界面中每打开一个包含了Ext.Grid(以下简称grid)控件的Ext.TabPanelItem(以下简称tab),浏览器(IEFx)占用的内存资源就会飙升14M,且关闭Ext.TabPanelItem后内存并不会被回收。如此,每次开启10Ext.TabPanleItem再将之关闭,反复数次之后,浏览器所占用的资源已经高达数百兆。浏览器内存占用提高的问题暂不考虑,因为tab中嵌入了iframe(由于系统页面结构的特殊性和接口问题,没有利用ajax请求向tab中装载页面内容),而iframe中的页面加载了PrototypeExtjs文件(总共大约600K),假设框架加载需要分配14M的内存空间也是合理的。但关闭tab后内存不被回收,且开启新tab时浏览器内存占用继续增长,则可以肯定地判断为内存泄露。是何种原因导致了内存泄露呢?

 

IE/Fxbugiframe惹祸

         经过进一步的观察,我们发现IEFx的内存泄露现象存在着差异,而浏览器瘫痪的时机也有着很大不同。

         具体表现如下:

         IE:每开启一个tabIE的内存占用量即提高14M。关闭tab,内存占用量不会下降。继续操作,直至浏览器瘫痪,内存占用量仍不下降。

         Fx:每开启一个tabFx的内存占用量提高14M。关闭tab,内存占用量不会下降。但连续关闭几个tab后,浏览器陷入假死状态,cpu占用率达到50%,数秒后恢复正常。tab全部关闭后,继续操作,随着tab的添加Fx的内存占用量又逐渐增加。

 

解决办法

         综上,可以得到这样的结论,IE下确实存在着内存泄露问题,而Fx下并非内存泄露导致浏览器假死。

         随后,我在Ext的官方网站论坛上找到了关于iframetab混用时会发生Memory leak的帖子。Ext核心开发人员Jack的回答是,TabPanelItem在关闭时并不会对自定义到tab中的元素做特殊处理,这部分工作必须在控件外来完成。另一方面,相关资料称IEiframe元素的回收方面存在着bug,在通常情况下应该将该元素的src属性值修改为"abort:blank",并手工将其从DOM树上移除,然后把脚本中引用它的变量置空并调用CollectGarbage()就可以避免iframe不能正常回收所造成的内存泄露。

         按照上述方法,在tabclose事件中添加了iframe的销毁代码,IE的内存泄露问题得以解决。

         但是,Fx的问题仍然无法得到解决,即关闭tabCPU占用率激增并持续数秒。无奈之下我测试了Linux下的Firefox以及Windows版本的Firefox 3 alpha,并未出现此问题。初步断定,着个问题应该是Firefox 2.0.0.4DOM元素回收性能方面的BUG。至于在Fx下关闭tab并不会立即释放内存也得到了官方解释,Fx会缓存一部分页面数据在内存中,以得到较好的性能。

 

“至尊”级浏览器,Safari

       此前我对苹果发布的windows版本Safai3还持有不屑一顾的态度,因为他们的发言人实在太过狂妄的发言,自称Safari是世界上最好的浏览器,未把任何浏览器放在眼里。我一向不喜欢自吹的人,却又对他们发言人的狂言感觉好奇,另一方面希望测试一下产品的跨浏览器能力,便索性下载了Safari 3 for windows。结果令我瞠目结舌,Safari处理JavaScript的速度绝非IEFx(包括他们的最新版本IE7Fx3 alpha)所能及,绝对可以堪称一流的页面渲染能力。为程序员说句心里话,如果所有浏览器的页面渲染速度能达到Safari的水准,我们在AJAX RIA应用构建上将有更大的发挥空间。我着实为Safari带来的RIA极速浏览体验快感兴奋了一把。不夸张地说,Safari至少可以算个浏览器的准至尊吧。

 

Extjs包使用注意事项

      在通常情况下,使用ext-all.js就可以了,但是当一个页面需要包含多个iframe,且iframe的资源指向需要使用Ext的页面时,被嵌入的页面尽量不要使用Ext-all.js了,而是使用ext-core.js并从Extpackage目录中加载你所需要的js包。除非你确定你的客户使用Safari或者Fx3来浏览,否则性能会大打折扣。






评论

  • 通常情况下应该将该元素的src属性值修改为"abort:blank",并手工将其从DOM树上移除,然后把脚本中引用它的变量置空并调用CollectGarbage()就可以避免iframe不能正常回收所造成的内存泄露。
    ---能不能放代码看看?我写怎么都不能释放内存

    as () 发表于 2008-12-09 22:11:32  [回复]
  • 兄弟,有没有研究过,ext window打开,关闭内存不能回收切dom删除回收不彻底的问题?

    毕竟红尘 () 发表于 2008-04-30 23:05:23  [回复]
  • tab改用remove方法代替close关闭试试看

    xjdawu () 发表于 2008-01-08 18:19:28  [回复]
  • 很详细,帮了我大忙,谢谢
    --------------------
    kirkmont001@bytefocus.com

    Robin 回复 kirkmont001 说:
    很高兴能对你有所帮助。
    之前忘记补充了,其实Fx本没有这个问题的,是我后来发现的,在Fx下的假死现象是由于Firebug导致的,将之disable掉之后不会再出现假死现象。
    (2007-11-12 20:52:14)

    kirkmont001 (http://hi.baidu.com/kirkmont001/blog) 发表于 2007-11-12 13:40:57  [回复]

发表评论

 姓名:
 E-mail:
 地址: