`
babydeed
  • 浏览: 235875 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

动态加载Javascript会导致内存泄露? rss文章订阅

    博客分类:
  • Ext
阅读更多

前些天在javaeye上发了一个帖子,“动态加载Javascript会导致内存泄露?”,自己当时被老外的那篇文章搞的比较困惑,网上也请教了一些高人,这里要非常感谢那些帮助我的人,工作非常繁忙的时候还愿意给我讲解他们对问题的看法,真的让我很感动!

 

这里再介绍一个比较好用的工具:Drip/sIEve,感谢jindw为我推荐这个工具,DripsIEve的作者应该是同一个人,连open souce上的项目都是在一起的。不过,平时我们主要使用sIEve就可以了,sIEve的功能比Drip强大一些,sIEve 是一个帮助我们查看ie浏览器(他本身基于操作系统安装的ie内核)内存的使用和内存泄露问题的。具体使用很简单,这里再提供一个链接给大家:http://home.orange.nl/jsrosman/,大家下载下来后就可以使用了。

Firefox下面也有一个检查内存泄露的工具,不过我用过,感觉有时候很让人抓狂,大家有兴趣的不妨也试试。PuterJam为我们总结了一篇“javascript 内存泄露工具使用”,推荐去看看。

来看我做的测试,代码1

<body>

<script type="text/javascript">

script = document.createElement('script');

script.src = 'little.js';

script.id = 'JSONP';

script.type = 'text/javascript';

script.charset = 'utf-8';

var head = document.getElementsByTagName('head')[0];

head.appendChild(script);

</script>

测试页面2

<script type="text/javascript">

var script = document.getElementById('JSONP');

script.parentNode.removeChild(script);

</script>

</body>

sIEve的结果是:



 

可以看到,id=JSONP的节点是孤立状态,而没有被回收 (还有一个孤立节点 大家不用管) ,为了解决这个办法,从EXTjs里面的代码得到灵感:


 

我把页面代码修改成:

<body>

<script type="text/javascript">

script = document.createElement('script');

script.src = 'little.js';

script.id = 'JSONP';

script.type = 'text/javascript';

script.charset = 'utf-8';

var body = document.getElementsByTagName('body')[0];

body.appendChild(script);

</script>

测试页面2

<script type="text/javascript">

var script = document.getElementById('JSONP');

var d = document.createElement('div');

d.appendChild(script);

d.innerHTML = '';

</script>

</body>

       可惜的是竟然还是存在没被回收的节点,囧!:


 

这里我暂时还不知道是什么原因,没仔细研究下去,如果是div的话,用这种方式是可以把节点回收的。

克军大牛跟我讲,“再加一行script = null;确实jsonp不能滥用,,一般解决dom的循环reference就是null掉”,于是我把最后的script对象null掉,发现果然节点不存在了!

       Code

<body>

<script type="text/javascript">

script = document.createElement('script');

var head = document.getElementsByTagName('head')[0];

head.appendChild(script);

script.src = 'little.js';

script.id = 'JSONP';

script.type = 'text/javascript';

script.charset = 'utf-8';

</script>

测试页面2

<script type="text/javascript">

var script = document.getElementById('JSONP');

script.parentNode.removeChild(script);

script = null;

</script>

</body>

结果图:


 

       看来还是不能想什么奇淫技巧,老老实实把最后的对象引用null

ranklau那天抽出时间跟我讲:“如果用htmlelementremove后会泄露。用fragmentfragment不用appendDOM上,不会有泄露。一个节点appenddom上,你再移除它就会有泄露的。所以才会出现象exttrash机制”,ranklau一看就是高手,我也是陋闻了,这些结论竟然都不知道!不过ranklau也是技术人员一贯的严谨作风,自己没去做测试,所以希望我能去做测试验证这些观点。今天上网找到了这方面的一个帖子,发现“这是IE的一个特点:document fragmentappenddocumentdom里面的时候,也可以拥有自己的脚本运行空间,可以用script标签发起请求。这样用document fragment就可以比iframe使用更少的客户端资源来完成操作。”好!做测试:

<body>

<script type="text/javascript">

var df = document.createDocumentFragment();

script = document.createElement('script');

script.src = 'little.js';

script.id = 'JSONP';

script.type = 'text/javascript';

script.charset = 'utf-8';

df.appendChild(script);

</script>

测试页面2

<script type="text/javascript">

var script = document.getElementById('JSONP');

alert(script);

</script>

</body>

测试结果:



 

 

id=JSONP的节点至始至终没有append到页面的dom树上来,是一个孤立的点,但是,null掉后也就被回收了,所以,这种方式也不错!

       最后,我却怀疑这个documentFragment会引起内存泄漏,因为浏览器要为这个新节点产生一个新的脚本scope,所以肯定会消耗额外的内存,至于到底是不是这样,还是测试:

       Code

<body>

<script type="text/javascript">

for(var i=0;i<100;i++){

         var dom = document.createDocumentFragment();

         script = document.createElement('script');

         script.src = 'little.js';

         script.id = 'JSONP';

         script.type = 'text/javascript';

         script.charset = 'utf-8';

         dom.appendChild(script);    

         dom.removeChild(script);

         script=null;

}

</script>

</body>

        

如图,发现,还是存在额外的内存消耗

最后,看网上有人说“IE8beta版本不支持documentFragment拥有独立的运行空间,正式版又解决了这个问题”,这个我不确定,因为我至今没装IE8,大家有兴趣可以去测试下,不过我觉得比较稳妥的方式还是最好别用documentFragment

 

转自:http://04js.cn/content.asp?id=1613

今天自己再次做了一些测试,和上次不一样,这次集中在IE上面(上次在firefox测试比较多),这几天的请教让我明白:IEfirefoxchrome的解析机制是不一样的,“对于需要频繁动态加载的script(比如跨域的jsonp接口),可以对ie做一下专门的优化,因为ieDom解析机制是c++写的,好像属于windows网络堆栈的那个部分,跟Javascript引擎的垃圾回收机制完全不同,内存泄漏问题比较明显……”,“firefox的内存GC机制比IE强悍,不必作为重点考虑对象。只要ie的问题能处理好,firefox上基本上也没有什么问题。”

分享到:
评论
1 楼 tipx 2010-07-02  
学习了

相关推荐

Global site tag (gtag.js) - Google Analytics