Поиск утечек памяти JavaScript с помощью Chrome
Я создал очень простой тестовый случай, который создает базовое представление, присоединяет обработчик к событию и создает экземпляр пользовательского класса. Я считаю, что, нажав кнопку "Удалить" в этом примере, все будет очищено и не должно быть никаких утечек памяти.
jsfiddle для кода находится здесь:http://jsfiddle.net/4QhR2/
// scope everything to a function
function main() {
function MyWrapper() {
this.element = null;
}
MyWrapper.prototype.set = function(elem) {
this.element = elem;
}
MyWrapper.prototype.get = function() {
return this.element;
}
var MyView = Backbone.View.extend({
tagName : "div",
id : "view",
events : {
"click #button" : "onButton",
},
initialize : function(options) {
// done for demo purposes only, should be using templates
this.html_text = "<input type='text' id='textbox' /><button id='button'>Remove</button>";
this.listenTo(this,"all",function(){console.log("Event: "+arguments[0]);});
},
render : function() {
this.$el.html(this.html_text);
this.wrapper = new MyWrapper();
this.wrapper.set(this.$("#textbox"));
this.wrapper.get().val("placeholder");
return this;
},
onButton : function() {
// assume this gets .remove() called on subviews (if they existed)
this.trigger("cleanup");
this.remove();
}
});
var view = new MyView();
$("#content").append(view.render().el);
}
main();
однако мне непонятно, как использовать профилировщик Google Chrome, чтобы убедиться, что это на самом деле случай. Есть миллион вещей, которые появляются на снимке профилировщика кучи, и я понятия не имею, как декодировать то, что хорошо/плохо. Учебники, которые я видел на нем до сих пор, либо просто говорят мне "использовать snapshot profiler", либо дают мне чрезвычайно подробный манифест о том, как работает весь профилировщик. Можно ли просто использовать профилировщик в качестве инструмента, или мне действительно нужно понять, как все это было сделано?
EDIT: учебные пособия как эти:
исправление утечки памяти Gmail
представляют собой некоторые из более сильных материалов там, из того, что я видел. Однако, помимо введения понятия 3 Техника Снимка, я считаю, что они предлагают очень мало с точки зрения практических знаний (для новичка, как я). Учебник "использование DevTools" не работает через реальный пример, поэтому его расплывчатая и общая концепция описание вещей не слишком полезно. Что касается примера "Gmail":
Итак, вы нашли утечку. И что теперь?
изучите путь сохранения просочившихся объектов в нижней половине панели профилей
Если сайт распределения не может быть легко выведен (т. е. прослушиватели событий):
инструмент конструктор удерживающего объекта через Консоль JS для сохранения трассировки стека для распределения
С Помощью Закрытия? Включите соответствующий существующий флаг (т. е. goog.события.Слушатель.ENABLE_MONITORING) для установки свойства creationStack во время строительства
Я нахожу себя более смущенным после прочтения этого, не меньше. И, опять же, это просто говорит мне do вещи, а не как чтобы сделать их. С моей точки зрения, информации там либо слишком расплывчато, либо будет иметь смысл только для тех, кто уже понял этот процесс.
некоторые из этих более конкретных вопросов были подняты в ответе @Jonathan Naguin ниже.
7 ответов:
хороший рабочий процесс для поиска утечек памяти является три снимка техника, впервые используемая Loreena Lee и командой Gmail для решения некоторых проблем с памятью. Шаги, в общем:
- сделайте снимок кучи.
- делать.
- сделать еще один снимок кучи.
- повторите то же самое.
- сделать еще один снимок кучи.
- фильтровать объекты, выделенные между снимками 1 и 2 в снимке 3 Вид" резюме".
для вашего примера, я адаптировал код, чтобы показать этот процесс (вы можете найти его здесь) задержка создания представления магистрали до события щелчка кнопки Пуск. Теперь:
- запустите HTML (сохраненный локально с помощью этого адрес) и сделать снимок.
- Нажмите кнопку Пуск, чтобы создать представление.
- сделайте еще один снимок.
- нажмите "Удалить".
- возьмите другой снимок.
- фильтровать объекты, выделенные между снимками 1 и 2 в представлении "сводка" снимка 3.
теперь вы готовы найти утечки памяти!
вы заметите узлы нескольких разных цветов. Красные узлы не имеют прямых ссылок из Javascript на них, но являются живыми, потому что они являются частью отдельного дерева DOM. В дереве может быть узел, на который ссылается Javascript (возможно, как закрытие или переменная), но по совпадению предотвращает все дерево DOM от сбора мусора.
желтые узлы, однако, имеют прямые ссылки из Javascript. Найдите желтые узлы в том же отдельном дереве DOM, чтобы найти ссылки из вашего Javascript. Должна быть цепочка свойств, ведущая от окна DOM к элементу.
в вашем конкретном случае вы можете увидеть элемент HTML Div, отмеченный красным цветом. Если вы развернете элемент, вы увидите, что на него ссылается функция "кэш".
выберите строку и в вашей консоли введите $0, вы увидите фактическую функцию и местоположение:
> function cache( key, value ) { // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) if ( keys.push( key += " " ) > Expr.cacheLength ) { // Only keep the most recent entries delete cache[ keys.shift() ]; } return (cache[ key ] = value); } jquery-2.0.2.js:1166здесь находится ссылка на ваш элемент. К сожалению, вы мало что можете сделать, это внутренний механизм от jQuery. Но, только для целей тестирования, перейдите в функцию и измените метод на:
function cache( key, value ) { return value; }теперь, если вы повторите процесс, вы не увидите ни одного красного узла :)
документы:
вот совет по профилированию памяти jsfiddle: используйте следующий URL-адрес, чтобы изолировать результат jsfiddle, он удаляет всю структуру jsfiddle и загружает только ваш результат.
http://jsfiddle.net/4QhR2/show/
Я никогда не мог понять, как использовать временную шкалу и профилировщик для отслеживания утечек памяти, пока не прочитал следующую документацию. После прочтения раздела под названием "трекер распределения объектов" я смог использовать " запись Инструмент выделения кучи и отслеживание некоторых отдельных узлов DOM.
я исправил проблему, переключившись с привязки событий jQuery на использование делегирования событий магистрали. Насколько я понимаю, новые версии Backbone автоматически отменят привязку событий для вас, если вы позвоните
View.remove(). Выполните некоторые из демонстраций самостоятельно, они настроены с утечками памяти для вас, чтобы идентифицировать. Не стесняйтесь задавать вопросы здесь, Если вы все еще не получили его после изучения этого документация.https://developers.google.com/chrome-developer-tools/docs/javascript-memory-profiling
в основном вам нужно посмотреть на количество объектов внутри вашего снимка кучи. Если число объектов возрастает между двумя снимками, и вы избавились от объектов, то у вас есть утечка памяти. Мой совет-искать обработчики событий в вашем коде, которые не отсоединяются.
вы также можете прочитать :
http://addyosmani.com/blog/taming-the-unicorn-easing-javascript-memory-profiling-in-devtools/
Он объясняет использование инструментов разработчика chrome и дает некоторые пошаговые советы о том, как подтвердить и найти утечку памяти с помощью сравнения снимков кучи и различных доступных представлений снимков hep.
вы также можете посмотреть вкладку Timeline в инструментах разработчика. Запишите использование вашего приложения и следите за количеством узлов DOM и прослушивателей событий.
Если график памяти действительно указывает на утечку памяти, то вы можете использовать профилировщик, чтобы выяснить, что происходит утечка.
Я второй совет, чтобы сделать снимок кучи, они отлично подходят для обнаружения утечек памяти, chrome делает отличную работу snapshotting.
в моем исследовательском проекте для моей степени я создавал интерактивное веб-приложение, которое должно было генерировать много данных, построенных в "слоях", многие из этих слоев будут "удалены" в пользовательском интерфейсе, но по какой-то причине память не была освобождена, используя инструмент моментального снимка, который я смог определить, что JQuery хранил a ссылка на объект (источник был, когда я пытался вызвать
.load()событие, которое сохранило ссылку, несмотря на выход из области видимости). Имея эту информацию под рукой в одиночку спас мой проект, это очень полезный инструмент, когда вы используете библиотеки других людей, и у вас есть эта проблема затяжных ссылок, останавливающих GC от выполнения своей работы.изменить: Также полезно заранее планировать, какие действия вы собираетесь выполнить, чтобы свести к минимуму время, затраченное на привязку, предположите, что может быть причиной проблемы, и протестируйте каждый сценарий, делая снимки до и после.


Comments