Phantomjs умирает из-за высокого потребления памяти

#javascript #memory-leaks #tfs #phantomjs

#javascript #утечки памяти #tfs #phantomjs

Вопрос:

Мы используем phantomjs для запуска нашей страницы тестов qunit на нашем сервере сборки TFS. Наша версия тестового бегуна построена на примере ниже

https://github.com/ariya/phantomjs/blob/master/examples/run-qunit.js

За определенный период времени количество тестов увеличилось с сотен до пары тысяч, и в один прекрасный день phantomjs начал сбоить. Он буквально умирает, говоря, что загружает дамп, и когда вы видите дамп, это 0 КБ!!

Когда мы более внимательно изучили это в process Explorer, мы обнаружили, что потребление памяти phantomjs продолжает расти, поскольку phantomjs выполняет тесты и в конечном итоге выходит из строя где-то на 833 МБ.

Да, тот же объем памяти использовался chrome и IE! И да-да, в наших тестах была утечка памяти:(. Мы исправили это, использование памяти снижено на 50% в Chrome и IE, и мы ожидали, что phantomjs теперь справится с этим. Но нет, phantomjs все еще продолжал сбой, process Explorer показывает такое же потребление памяти.

http://phantomjs.org/api/webpage/method/close.html

Согласно приведенной выше документации, phantomjs освобождает выделение кучи только при закрытии? Может ли это быть причиной того, что наш фиксированный тест потреблял меньше памяти в Chrome, но не в phantomjs? И последнее, как это исправить? Как заставить phantomjs продолжать собирать мусор, собирая объекты javascript, чтобы уменьшить выделение кучи?

Обновление 1 — 07/28

Мы решили обойти проблему. Я изменил свой скрипт для выполнения моих тестов по модулю за модулем. В цикле после выполнения всех тестов для модуля я вызываю page.close, чтобы он освобождал память для каждого модуля и никогда не продолжал создавать мертвую кучу объектов. Не закрываю этот вопрос, поскольку это обходной путь, а не решение. Надеюсь, создатели когда-нибудь это исправят.

Комментарии:

1. Какие структуры данных вы загрузили на свою веб-страницу, чтобы использовать 833 МБ? Это безумие! Я никогда не слышал о веб-приложении, занимающем столько памяти.

2. @CameronTinker Когда приложение запускается автономно, оно не превышает 90 МБ и остается там в течение всего срока службы. Это одностраничное приложение, созданное с использованием EmberJS. Потребление 833 МБ приходится на страницу запуска теста qunit ..

Ответ №1:

Существует статический метод, QWebPageSettings::clearMemoryCache , который вызывает сборку мусора WebKit. Однако он очищает весь кэш памяти QWebPage для каждого созданного экземпляра объекта QWebPage и поэтому в настоящее время не подходит для включения в качестве опции в PhantomJS.

Запрос на извлечение Github доступен здесь:
https://github.com/ariya/phantomjs/pull/11511
Вот обсуждение групп Google:
https://groups.google.com/forum /#!сообщение/phantomjs/wIDp9J7B-bE/v5U31_mTbswJ

Пока не будет доступно обходное решение, вы можете разбить свои модульные тесты на блоки на отдельных страницах. Потребуется внести изменения в реализацию QtWebKit и в то, как память / кэш обрабатываются в объектах QWebPage.

Обновление за сентябрь 2014 года: https://github.com/ariya/phantomjs/commit/5768b705a0
Похоже, была добавлена поддержка очистки кэша памяти, но в коммите есть примечание о моем первоначальном комментарии.

Комментарии:

1. Спасибо, что поделились этой информацией @Cameron Tinker

2. @lame_coder вы выяснили, как получить доступ к page объекту из вашего набора тестов, чтобы вызвать этот метод? Я сталкиваюсь с той же проблемой с Phantom2 и Ember JS.

3. В PhantomJS 2.0 через Selenium webdriver 1.2.0 это webdriver.executePhantomJS("phantom.page.clearMemoryCache()", []) . Однако это не будет работать при GCing dom (например, Iframes в одностраничном приложении), оно просто очищает кэшированные изображения в памяти и тому подобное.

4. @NielsK вы знаете, доступно ли оно в версии 1.9.8? Я пытался page.clearMemoryCache() и phantom.page.clearMemoryCache() , но в обоих случаях я получил ReferenceError: Can't find variable:

5. @Erin_Drummond Нет, эта функция была добавлена с переходом на PhantomJS 2

Ответ №2:

Мне удалось обойти это, установив флаг /LARGEADDRESSAWARE

Если у вас установлена Visual Studio, запустите из командной строки Visual Studio

 editbin /LARGEADDRESSAWARE <pathto>/PhantomJS.exe