DOM Parser Chrome扩展内存泄漏

时间:2019-06-04 21:43:23

标签: javascript browser google-chrome-extension memory-leaks domparser

问题

我开发了一个扩展程序,用于拦截Web请求,获取Web请求所源自的HTML并对其进行处理。我已经使用DOMParser解析HTML,并且我意识到DOMParser会导致大量内存泄漏问题,最终导致chrome扩展崩溃。

这是导致问题的代码。 https://gist.github.com/uche1/20929b6ece7d647250828c63e4a2ffd4

我尝试过的

Dev工具记录的性能

我在chrome扩展程序拦截请求时记录了下来,我注意到当DOMParser.parseFromString方法被调用时,创建了更多的未破坏的节点和文档。

Dev工具截图 https://i.imgur.com/pMY50kR.png

任务管理器的内存占用量

我看了看chrome上的任务管理器,发现它具有巨大的内存占用,并且不会随着时间的推移而减少(因为垃圾收集会在一段时间后启动)。当内存占用空间太大时,扩展程序崩溃。

任务管理器内存占用量屏幕截图 https://i.imgur.com/c8fLWCy.png

堆快照

我在堆的屏幕截图之前和之后都做了一些操作,我可以看到问题似乎是由于分配的HTMLDocuments引起的,而这些HTMLDocuments并没有被垃圾收集。

快照(之前) https://i.imgur.com/Rg2CRi6.png

快照(之后) https://i.imgur.com/UQgLuT1.png

预期结果

我想了解为什么DOMParser导致了此类内存问题,为什么垃圾回收器未对其进行清理以及解决该问题的方法。

谢谢

2 个答案:

答案 0 :(得分:1)

您基本上是在内存中复制整个DOM,然后再也不释放内存。

我们在客户端应用程序中避免了这个问题,因为当我们离开时,该页面上脚本所使用的内存将被恢复。

在后台脚本中,这不会发生,现在是您的责任。

使用完毕,请将parserdocument都设置为null

chrome.webRequest.onCompleted.addListener(async request => {
    if (request.tabId !== -1) {
        let html = await getHtmlForTab(request.tabId);
        let parser = new DOMParser();
        let document = parser.parseFromString(html, "text/html");
        let title = document.querySelector("title").textContent;
        console.log(title);
        parser = null; // <----- DO THIS
        document = null; // <----- DO THIS
    }
}, requestFilter);

答案 1 :(得分:0)

我已经解决了问题。看来问题出在这是因为DOMParser类出于某种原因在内存中保留了它解析的HTML文档的引用,但没有释放它。由于我的扩展程序是在后台运行的Chrome扩展程序,因此会夸大此问题。

解决方案是使用另一种解析HTML文档的方法

let parseHtml = (html) => {
    let template = document.createElement('template');
    template.innerHTML = html;
    return template; 
}

这有助于解决问题。