Подтвердить что ты не робот

Устранение утечки памяти из дерева DOM

У меня возникла проблема с диагностикой утечки памяти отдельного дерева DOM в очень большом одностраничном веб-приложении, созданном в основном с помощью Knockout.

Я настроил приложение, чтобы прикрепить объект dummy FooBar к определенному элементу кнопки HTML, который должен быть собран с помощью мусора, когда пользователь переходит на другую "страницу" приложения. Используя функцию моментального снимка кучи Chrome, я вижу, что старый FooBar экземпляр (который должен был быть GC'ed) по-прежнему доступен из его HTMLButtonElement в (большом) отдельном дереве DOM.

Отслеживая ссылки через панель сохранения дерева, я следую за цепочкой, уменьшающей расстояние от корня GC. Однако в какой-то момент мой поиск достигает тупика на расстоянии node от корня (в данном случае)! Сохраняющее дерево вообще не сообщает об этом node, но как-то знает, что оно находится в четырех шагах от корня GC.

Вот часть удерживающего дерева, которое меня озадачивает (числа справа являются расстояниями от корня):

v foobar in HTMLButtonElement                                  10
  v [4928] in Detached DOM tree / 5643 entries                  9
    v native in HTMLOptionElement                               8
      v [0] in Array                                            7
        v mappedNodes                                           6
          v [870] in Array                                      5
            v itemsToProcess in system / Context                4
                context in function itemMovedOrRetained()
                context in function callCallback()

Сохраняющее дерево не показывает ссылки здесь на расстоянии 3 или выше.

Может кто-нибудь объяснить это мне? Я надеялся, что смогу следить за ссылочной цепочкой, чтобы вернуться к нарушающей части кода приложения JavaScript, но у меня все в порядке!

4b9b3361

Ответ 1

Прежде всего - не используйте delete как один из предложенных комментариев. Установка ссылки на null - это правильный способ избавиться от вещей. delete разбивает "скрытый класс". Чтобы убедиться в этом, запустите мои примеры из https://github.com/naugtur/js-memory-demo

Rafe, контент, который вы видите в профилировщике, часто трудно понять. Бит, который вы разместили здесь, кажется странным и может быть ошибкой или утечкой памяти за пределами вашего приложения (утечки браузеров тоже), но без запуска приложения это трудно сказать. Ваше удерживающее дерево заканчивается в контексте функции, и его можно сохранить ссылкой на эту функцию или какую-либо другую функцию, совместно использующую контекст. Профилировщик может быть слишком сложным, чтобы визуализировать его правильно.

Я могу помочь вам точно определить проблему.

Сначала перейдите на вкладку Timeline в devtools и используйте ее, чтобы наблюдать, как происходит утечка. Выберите только распределение памяти и начните запись. Пройдите сценарий, который вы ожидаете утечки. Балки, которые остаются синими, являются утечками. Вы можете выбрать их окружение на временной шкале и сосредоточиться на их сохраняющем дереве. Самые интересные элементы в отдельно стоящих домиках - красные - на них ссылаются снаружи. Остальное сохраняется, потому что любой элемент в дереве ссылается, он ссылается на все остальное (x.parentNode)

Если вам нужна дополнительная информация, вы можете сделать несколько снимков в профилировщике, чтобы у вас был моментальный снимок до и после причины утечки (которую вы нашли на временной шкале - теперь вы знаете точное действие, которое его вызывает), Затем вы можете сравнить их в профилировщике - там есть "сравнить". что более понятно, чем другие.

Вы также можете сохранить снимки кучи из профилировщика и опубликовать их в Интернете, чтобы мы могли посмотреть. Там есть ссылка сохранения на каждом из них в списке слева.


Профилирование памяти затруднено и на самом деле требует некоторой практики и понимания инструментов. Вы можете попрактиковаться в некоторых примерах из моего разговора:

http://naugtur.pl/pres/mem.html#/5/2

но реальное полное руководство по использованию профилировщика памяти - это документ:

https://developer.chrome.com/devtools/docs/javascript-memory-profiling#looking_up_color_coding

Обновленная ссылка: https://developers.google.com/web/tools/profile-performance/memory-problems/memory-diagnosis