0
回答
jQuery 内存泄露追踪(附解决方案)
华为云4核8G,高性能云服务器,免费试用   

场景

异步回调,解析HTML,过滤出某一部分,加载到页面。

我的代码

  html = $(html) ;

追踪

经查: jQuery在解析Html时,会有内存泄露。追踪的执行代码如下:

1. init:

if (typeof selector === "string")

...

ret = jQuery.buildFragment([match[1]], [doc]);

2. buildFragment

jQuery.clean(args, doc, fragment, scripts);

3.clean 这才是核心,还不明白为什么起这个名字。 分析文章: http://www.cnblogs.com/nuysoft/archive/2012/01/11/2318651.html

div = context.createElement("div"), // 重点关注对象 .

safeChildNodes = safeFragment.childNodes, //safeFragment 是在加载完jQuery之后执行的。 它只是进行了创建,并没有追加到 DOM 中。

...

// Append wrapper element to unknown element safe doc fragment
if (context === document) {
// Use the fragment we've already created for this document
safeFragment.appendChild(div); //把div添加到 safeFragment,作用何在? 
} else {
// Use a fragment created with the owner document
createSafeFragment(context).appendChild(div);
}

...

div.innerHTML = wrap[1] + elem + wrap[2]; //内存开始增长。之后并没有回落,怀疑是清理有问题。

...

div.parentNode.removeChild(div); //很明显,作者想到了要清理,但根据监测结果,内存并没有回落。在HTML内容很大的情况下,观察效果明显。

 

解决方案

作者的方案是,创建div,把它添加到 Fragment,再设置 innerHTML,和网上流传的

url: http://archive.cnblogs.com/a/2260680/

出现这种内存泄漏需要有三个条件:  1. 内存中存在一个未加入DOM树的元素  2. 给这个元素设置innerHTML,注意,必须是能创建元素并且绑定了DOM 0级事件  3. 必须在这个元素加入DOM树前设置它的innerHTML

思想如出一辙,但有不同。

把我的代码按网上方案进行改造。

 

var div = document.createElement("div");
document.body.appendChild(div) ;
div.innerHTML = html ;

html = $(div.childNodes );

...

 

document.body.removeChild(div);

 

使用 Drip,进行测试,使用 Show Memory Usage 查看,内存增加非常小,使用 Show Dom Usage 查看,曲线还是很明显(但点Show Dom Leaks,页面会变白)

使用 sIEve 进行测试,使用 Show Memory Usage 查看,内存增长曲线非常小。使用 Show Dom Usage 查看,曲线基本持平。

使用 任务管理器进行查看,发现内存可以回落。 sIEve 比 Drip 要准确。

下图是 sIEve 的两个曲线图:

 

效果还是不错的。


原文链接:http://www.cnblogs.com/newsea/archive/2012/06/25/2561201.html
举报
长平狐
发帖于6年前 0回/716阅
顶部