Проблемы с памятью Javascript и проблемы с утечкой

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

Я пытаюсь сделать оценку JS-памяти на своем сайте. Я сделал это, посмотрев диспетчер задач Chrome и с помощью снимков кучи.

Первоначально мой сайт при первом загрузке находится между 35 МБ (т.е. 35 000 КБ) и 40 МБ в диспетчере задач. Это самая большая из всех вкладок, если у меня одновременно есть несколько вкладок других сайтов. Если я верну его страницу до 55-60, другое обновление увидит, что оно переместится на 65-70 МБ.

На обычной странице в рабочем потоке она колеблется между 45-65 (иногда 75 в зависимости от того, что вы делаете). Щелчок вокруг и выполнение рабочего процесса со страницы на страницу видит, что память прыгает до 85-100 и увеличивается по мере того, как вы продолжаете работу с сайтом.

Я попытался сделать несколько вещей, например, проверить:

  • деактивированные узлы
  • снимки кучи и просмотр дельт
  • amix MemoryLeakChecker проверяет размер объектов

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

Снимки кучи не отображают много, большинство верхних списков - это (массив), (строка), (система). Снимки располагаются между 4.8MB, 5.1MB, 5.8MB, 6.8MB и увеличиваются.

У меня есть несколько вопросов:

  • How do I understand the different metrics between snapshot memory and task manager memory
  • Are there any good tutorials (apart from the ones on the Google Developers site)?
  • How much memory is considered acceptable? Given in the task manager my site is always the highest?
  • Do I have a memory leak? Apart from the steps I've described above (which I haven't found anything concrete from) is there any other ways I can find leaks?
  • Can you suggest any tools apart from the Chrome Dev Tools (a lot of the tools mentioned on Google for Firefox are not compatible with the latest version, eg: Leak Monitor for FF)

В качестве основной заметки большинство моих функций - операции с низким ключом и не превышают 200 мс (на основе профиля процессора). На что я должен стремиться? Максимум 200 мс?

Ответы

Ответ 1

То, что вы описываете, - это не утечка памяти, это мусор, о котором знает Хром, и который будет удален, когда Хром решит это сделать. Чтобы объяснить это, давайте более подробно рассмотрим описанный вами сценарий.

Устранение утечки памяти

  • Сначала откройте новое окно инкогнито (просто чтобы убедиться, что расширения браузера не влияют на наши результаты) и перейдите на страницу google.com.
  • Затем откройте диспетчер задач и включите столбец "Память JavaScript" (щелкнув правой кнопкой мыши на окне диспетчера задач). Нам нужен этот столбец, чтобы быть уверенным, что память, которую мы будем "утечки", фактически выделяется JavaScript. Мы закончили с чем-то вроде этого:

First load

  • Теперь, как вы сказали, мы должны перезагрузить страницу пару раз и наблюдать за памятью нашей вкладки:

After 5+ reloads

До сих пор так хорошо - все работает точно так, как вы его описали.

Подождите секунду...

Однако за полминуты не двигайте курсором или переходите на другую вкладку, и вы увидите огромное количество использования памяти на нашей вкладке "Tab: google". Почему это? Что там произошло? Кто очистил нашу "утечку" памяти для нас?

Снижение использования памяти

Чтобы исследовать это, повторим то, что мы сделали до сих пор, так что "Tab: google" снова использует много памяти. Затем откройте Chrome Developer Tools и начните запись на вкладке "Timeline". После этого давайте изменим вкладку на пару секунд, и когда падение памяти прекратит запись на "временной шкале". Вы должны в итоге:

enter image description here

В последние пару секунд нашей записи появились загадочные "GC Events". Точно в то же время, когда память была выпущена. Совпадение? Нет.

События GC

GC означает Сборщик мусора. Это механизм, который "пытается вернуть мусор или память, занятую объектами, которые больше не используются программой". Таким образом, оказывается, что память нашей вкладки была загрязнена мусором, и GC был способен избавиться от этих мусора в течение всего времени (вы даже можете заставить сбор мусора использовать кнопку в нижней части вкладки "Временная шкала" ). Так почему он решил не делать этого? Почему он ждал, когда мы перестанем взаимодействовать со страницей или изменим вкладку?

Коллектив мусора с ленивым мусором

Короткий ответ заключается в том, что сбор мусора должен "заморозить" выполнение всех скриптов, прежде чем любая работа может быть выполнена. Кроме того, для выполнения может потребоваться значительное количество процессорного времени. Это может привести к задержке, прерывистой анимации, невосприимчивым элементам управления и т.д. Поэтому Chrome ждет подходящего момента, чтобы вызвать сбор мусора. И лучший момент для этого - когда пользователь не смотрит.

Кроме того, обратите внимание, что "GC Events" входят в серию, всегда есть пара из них с короткими перерывами между ними. Эти перерывы предназначены для "нормального" JavaScript для выполнения, делая сбор мусора менее заметным.

Живые объекты

Взгляните на вкладку "Память JavaScript" в двух верхних скриншотах в этом сообщении. Вы заметите, что этот столбец содержит два числа. Первый - это память ", зарезервированная для JavaScript VM heap ", другой -" сколько объектов памяти доступно (достижимых) (источник). При тестировании ваших приложений вы должны беспокоиться только о втором значении, все остальные будут обрабатываться GC.

Пример утечки

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

Заключение

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

Ответ 2

Если вы все еще думаете, что ваша страница протекает, вы можете использовать ответ этого вопроса для отслеживания просочившихся объектов.