Я создал очень простой контрольный пример, который создает представление Backbone, присоединяет обработчик к событию и создает экземпляр пользовательского класса. Я полагаю, что при нажатии кнопки «Удалить» в этом примере все будет очищено и не должно быть утечек памяти.
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, чтобы убедиться, что это действительно так. На снимке профилировщика кучи есть несколько миллиардов вещей, и я понятия не имею, как декодировать, что хорошо / плохо. Обучающие программы, которые я видел до сих пор, либо просто говорят мне «использовать профилировщик снимков», либо дают мне очень подробный манифест о том, как работает весь профилировщик. Можно ли просто использовать профилировщик в качестве инструмента или мне действительно нужно понять, как все это было спроектировано?
РЕДАКТИРОВАТЬ: Учебники, подобные этим:
Устранение утечки памяти в Gmail
Представляют некоторые из более сильных материалов, из того, что я видел. Однако, помимо представления концепции 3 Snapshot Technique , я считаю, что они предлагают очень мало с точки зрения практических знаний (для начинающего, как я). Учебное пособие «Использование DevTools» не работает на реальном примере, поэтому его расплывчатое и общее концептуальное описание вещей не слишком полезно. Что касается примера «Gmail»:
Итак, вы нашли утечку. Что теперь?
Изучите пути утечки предметов в нижней половине панели «Профили».
Если сайт размещения не может быть легко выведен (например, слушатели событий):
Инструментарий конструктора сохраняющего объекта через консоль JS для сохранения трассировки стека для выделений
Используя Закрытие? Включите соответствующий существующий флаг (например, goog.events.Listener.ENABLE_MONITORING), чтобы установить свойство creationStack во время построения.
После прочтения я чувствую себя более растерянным, а не менее. И, опять же, это просто говорит мне делать вещи, а не как это делать. С моей точки зрения, вся информация либо слишком расплывчата, либо будет иметь смысл только для тех, кто уже понял этот процесс.
Некоторые из этих более конкретных вопросов были подняты в ответе @Jonathan Naguin ниже.
источник
main
10000 раз, а не один раз, и посмотреть, не окажется ли у вас больше памяти в конце.Ответы:
Хороший рабочий процесс для обнаружения утечек памяти - это метод трех снимков , впервые использованный Лориной Ли и командой Gmail для решения некоторых проблем с памятью. Шаги, в общем:
Для вашего примера я адаптировал код, чтобы показать этот процесс (вы можете найти его здесь ), откладывающий создание Backbone View до события click кнопки Start. Сейчас:
Теперь вы готовы обнаружить утечки памяти!
Вы заметите узлы нескольких разных цветов. Красные узлы не имеют прямых ссылок из Javascript на них, но живы, потому что они являются частью отдельного дерева DOM. Может быть узел в дереве, на который ссылается Javascript (может быть, как замыкание или переменная), но по совпадению предотвращает сборку мусора всего дерева DOM.
Желтые узлы, однако, имеют прямые ссылки из Javascript. Ищите желтые узлы в том же отдельном дереве DOM, чтобы найти ссылки из вашего Javascript. Должна быть цепочка свойств, ведущая от окна DOM к элементу.
В частности, вы можете увидеть элемент HTML Div, помеченный как красный. Если вы развернете элемент, то увидите, что на него ссылается функция «кеш».
Выберите строку и в консоли введите $ 0, вы увидите фактическую функцию и местоположение:
Здесь ссылка на ваш элемент. К сожалению, вы мало что можете сделать, это внутренний механизм от jQuery. Но просто для целей тестирования перейдите к функции и измените метод на:
Теперь, если вы повторите процесс, вы не увидите ни одного красного узла :)
Документация:
источник
$0
в консоль функции, которая была для меня новой - конечно, я понятия не имею, что она делает или как вы знали, как ее использовать ($1
кажется бесполезным, хотя,$2
кажется, делает то же самое). Во-вторых, как вы узнали, чтобы выделить строку,#button in function cache()
а не другие десятки строк? Наконец, есть красные узлыNodeList
иHTMLInputElement
тоже, но я не могу понять их.cache
строка содержит информацию, а остальные нет? Есть множество ветвей, которые имеют меньшее расстояние, чем этоcache
. И я не уверен, откуда ты знал, чтоHTMLInputElement
это дитяHTMLDivElement
. Я вижу, что на него ссылаются внутри («родной в HTMLDivElement»), но он также ссылается на себя и дваHTMLButtonElement
s, что не имеет смысла для меня. Я, конечно, ценю, что вы определили ответ для этого примера, но я действительно не знаю, как обобщить это на другие вопросы.Filter objects allocated between Snapshots 1 and 2 in Snapshot 3's "Summary" view.
значит?Вот совет по профилированию памяти jsfiddle: используйте следующий URL, чтобы изолировать ваш результат jsfiddle, он удаляет всю структуру jsfiddle и загружает только ваш результат.
http://jsfiddle.net/4QhR2/show/
Я так и не смог понять, как использовать Timeline и Profiler для отслеживания утечек памяти, пока не прочитал следующую документацию. После прочтения раздела, озаглавленного «Трекер размещения объектов», я смог использовать инструмент «Запись выделения кучи» и отследить некоторые отдельные узлы DOM.
Я исправил проблему, переключившись с привязки событий jQuery на делегирование событий Backbone. Насколько я понимаю, более новые версии Backbone автоматически отменят привязку событий для вас, если вы позвоните
View.remove()
. Выполните некоторые демонстрации самостоятельно, они настроены с утечками памяти, чтобы вы могли их идентифицировать. Не стесняйтесь задавать вопросы здесь, если вы все еще не получили его после изучения этой документации.https://developers.google.com/chrome-developer-tools/docs/javascript-memory-profiling
источник
В основном вам нужно посмотреть на количество объектов в вашем снимке кучи. Если число объектов увеличивается между двумя моментальными снимками, и вы избавились от объектов, то у вас есть утечка памяти. Мой совет - искать обработчики событий в вашем коде, которые не отсоединяются.
источник
Window/http://jsfiddle.net/4QhR2/show
может быть полезно, но это просто бесконечные функции. Я понятия не имею, что там происходит.Есть вводное видео от Google, которое будет очень полезно для обнаружения утечек памяти JavaScript.
https://www.youtube.com/watch?v=L3ugr9BJqIs
источник
Вы также можете посмотреть на вкладку Timeline в инструментах разработчика. Запишите использование вашего приложения и следите за количеством DOM Node и Event listener.
Если график памяти действительно указывает на утечку памяти, то вы можете использовать профилировщик, чтобы выяснить, что происходит утечка.
источник
Вы также можете прочитать:
http://addyosmani.com/blog/taming-the-unicorn-easing-javascript-memory-profiling-in-devtools/
Он объясняет использование инструментов разработчика Chrome и дает несколько пошаговых советов о том, как подтвердить и обнаружить утечку памяти с помощью сравнения снимков кучи и различных доступных представлений снимков hep.
источник
Я второй совет, чтобы сделать снимок кучи, они отлично подходят для обнаружения утечек памяти, Chrome отлично делает снимок.
В своем исследовательском проекте для моей степени я создавал интерактивное веб-приложение, которое должно было генерировать много данных, построенных в «слоях», многие из этих слоев были бы «удалены» в пользовательском интерфейсе, но по какой-то причине память не была будучи освобожденным, используя инструмент моментальных снимков, я смог определить, что JQuery сохранял ссылку на объект (источник был, когда я пытался вызвать
.load()
событие, которое сохраняло ссылку, несмотря на выход из области видимости). Имея под рукой эту информацию, единолично сохранивший мой проект, это очень полезный инструмент, когда вы используете библиотеки других людей, и у вас есть проблема с давними ссылками, мешающими GC выполнять свою работу.РЕДАКТИРОВАТЬ: также полезно заранее планировать, какие действия вы собираетесь выполнять, чтобы минимизировать время, затрачиваемое на создание снимков, выдвигать гипотезы о том, что может быть причиной проблемы, и тестировать каждый сценарий, делая снимки до и после.
источник
Несколько важных замечаний, касающихся выявления утечек памяти с помощью инструментов Chrome Developer:
1) Сам Chrome имеет утечки памяти для определенных элементов, таких как поля пароля и номера. https://bugs.chromium.org/p/chromium/issues/detail?id=967438 . Избегайте их использования при отладке, так как они создают ваш снимок кучи при поиске отдельных элементов.
2) Избегайте регистрации чего-либо на консоли браузера. Chrome не будет собирать объекты, записанные на консоль, что повлияет на ваш результат. Вы можете подавить вывод, поместив следующий код в начало скрипта / страницы:
3) Используйте снимки кучи и ищите «detach», чтобы идентифицировать отдельные элементы DOM. При наведении курсора на объекты вы получаете доступ ко всем свойствам, включая id и outerHTML, которые могут помочь идентифицировать каждый элемент. Если отсоединенные элементы все еще слишком универсальны для распознавания, назначьте им уникальные идентификаторы с помощью консоли браузера перед запуском теста, например:
Теперь, когда вы идентифицируете отдельный элемент с помощью, скажем, id = "AutoId_49", перезагрузите страницу, снова выполните приведенный выше фрагмент и найдите элемент с id = "AutoId_49" с помощью инспектора DOM или document.querySelector (..) , Естественно, это работает, только если содержание вашей страницы предсказуемо.
Как я запускаю свои тесты для выявления утечек памяти
1) Загрузить страницу (с подавленным выводом на консоль!)
2) Делать вещи на странице, которые могут привести к утечкам памяти
3) Используйте Developer Tools, чтобы сделать снимок кучи и выполнить поиск «detach»
4) Наведите указатель мыши на элементы, чтобы идентифицировать их по свойствам id или outerHTML
источник