Утечка памяти в расширении DOM Parser Chrome - PullRequest
0 голосов
/ 05 июня 2019

Проблема

Я разработал расширение, которое перехватывает веб-запросы, получает HTML-код веб-запроса и обрабатывает его.Я использовал DOMParser для разбора HTML, и я понял, что DOMParser вызывает серьезные проблемы с утечкой памяти, что в конечном итоге приводит к сбою расширения chrome.

Это код, который вызывает проблемы.https://gist.github.com/uche1/20929b6ece7d647250828c63e4a2ffd4

Что я пробовал

Dev Tools Записанная производительность

Я записал расширение Chrome, пока оно перехватывает запросы, и заметил, что в качестве метода DOMParser.parseFromStringбыло вызвано, тем больше было создано узлов и документов, которые не были уничтожены.

Скриншот инструментов разработчика https://i.imgur.com/pMY50kR.png

След памяти для диспетчера задач

Я посмотрел на диспетчер задачна chrome и увидел, что у него огромный объем памяти, который не уменьшится со временем (потому что сборка мусора должна начаться через некоторое время).Когда объем памяти становится слишком большим, расширение падает.

Снимок экрана памяти диспетчера задач https://i.imgur.com/c8fLWCy.png

Снимки кучи

Я сделал несколько снимков экрана до и после иЯ вижу, что проблема, похоже, связана с выделением HTMLDocuments, который не подвергается сборке мусора.

Снимок (до) https://i.imgur.com/Rg2CRi6.png

Снимок (после) https://i.imgur.com/UQgLuT1.png

Ожидаемый результат

Я бы хотел понять, почему DOMParser вызывает такие проблемы с памятью, почему он не очищается сборщиком мусора и что нужно делать для его устранения.

Спасибо

Ответы [ 2 ]

1 голос
/ 05 июня 2019

Вы в основном реплицируете весь DOM в памяти, а затем никогда не освобождаете память.

Мы избегаем этого в клиентском приложении, потому что когда мы покидаем его, память, используемая сценариями на этой странице, восстанавливается.

В фоновом скрипте этого не происходит и теперь вы несете ответственность.

Так что установите parser и document на 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);
0 голосов
/ 05 июня 2019

Я решил проблему. Похоже, проблема была в том, что класс DOMParser по какой-то причине сохранил ссылки на документы HTML, которые он анализировал в памяти, и не выпустил его. Поскольку мое расширение является расширением Chrome, которое работает в фоновом режиме, преувеличивает эту проблему.

Решением было использование другого метода парсинга HTML-документа, который должен был использовать

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

Это помогло решить проблему.

...