JavaScript: стоит ли беспокоиться об утечках памяти в 2011 году - PullRequest
23 голосов
/ 12 сентября 2011

Тема утечек памяти в JavaScript поднимается не часто.Однако я наткнулся на эту статью , написанную в 2007 году. Авторы утверждают:

Internet Explorer и Mozilla Firefox - это два веб-браузера, которые чаще всего связаны с утечками памяти в JavaScript.

Стоит ли мне беспокоиться об утечках памяти JavaScript в 2011 году?Если да, то о чем мне следует быть осторожным?

Ответы [ 5 ]

12 голосов
/ 12 сентября 2011

Да, утечки памяти - определенно проблема в JavaScript, поскольку циклические ссылки действительно возможны. Очень распространенным источником утечек памяти является использование замыканий. В качестве примера рассмотрим:

var outerFunction = function(param1, param2, param3) {
     var innerFunction = function() {};
     return innerFunction;
};

Возможно, что вышеупомянутое утечка параметров, так как innerFunction содержит ссылку на область, в которой он был построен, который включает в себя параметры этого кадра.

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

Обратите внимание, что эти проблемы связаны с кодом JavaScript, написанным веб-разработчиками. Утечки памяти в базовых интерпретаторах JavaScript, хотя и возможны, представляют собой гораздо меньшую проблему, и это не то, о чем могут разумно беспокоиться веб-разработчики, поскольку это работа авторов браузеров.

12 голосов
/ 12 сентября 2011

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

ДляНапример, сохранение ссылки на любой объект DOM в переменной javascript будет поддерживать этот объект DOM живым в памяти, даже если он давно был удален из DOM, и вы намеревались освободить его.

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

  1. Все, что я делаю по таймеру, особенно, если его можно оставить на долгое время.Например, если у вас есть слайд-шоу, которое может просто зацикливаться вечно, вы должны быть абсолютно уверены, что в слайд-шоу ничто не является накопительной утечкой объектов JS или DOM.
  2. Веб-страница, которая работает как приложениеи пользователь может оставаться на одной и той же странице в течение длительного времени, взаимодействуя со страницей, совершая Ajax-вызовы и т. д.и множество взаимодействий пользователей и серверов.
  3. Веб-страница, которая регулярно создает и уничтожает множество элементов DOM, таких как что-то, что регулярно использует ajax для получения множества новых HTML.

Placesгде я действительно не беспокоюсь об утечках:

  1. Веб-страница, которая не имеет длительного набора взаимодействий, которые пользователь может выполнять.
  2. Веб-страница, которая не 'не оставайтесь на экране задолго до загрузки какой-либо другой страницы или перезагрузки этой страницы.

Некоторые ключевые моменты, за которыми я следю.

  1. Любые долговременные переменные или свойства JS, которые содержат ссылки на элементы DOM при создании / уничтожении элементов DOM.
  2. Любые свойства объекта DOM, которые содержат ссылки на другие объекты DOM илиссылки на объекты JS, которые содержат ссылки на другие объекты DOM (это может создавать циклические ссылки и перекрестные ссылки между JS / DOM, которые некоторые старые браузеры имеют проблемы с освобождением).
  3. Любые большие структуры данных, которые я загружаю для временного использования.Я уверен, что никакие ссылки на эти большие структуры данных не хранятся.
  4. Кэши данных.Убедитесь, что ничто действительно большое не кэшируется, что вы не хотите кэшировать.Убедитесь, что все кэши, которые используются неоднократно, не накапливаются вечно и имеют какой-то механизм старения, чтобы избавиться от старых объектов.
7 голосов
/ 04 октября 2011

NO.

Более полный ответ: возможно.Тот факт, что вы спрашиваете так смутно, является сильным сигналом о том, что вам лично вряд ли стоит беспокоиться.

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

Есть только несколько вопросов, на которые вам нужно ответить:

В: Поддерживаете ли вы полнофункциональное одностраничное приложение, которое интенсивно использует JavaScript?

Если нет, то не тратьте время на беспокойство.Если вы (или ваш QA, или ваши клиенты) обнаружите проблему чрезмерного использования памяти со страницей, то исправьте ее, когда она появится.

Q: Вам нужна поддержка мобильных устройств, и у вас тяжелый JavaScriptиспользование?

Мобильные устройства имеют ограниченную память, и необходимо проявлять особую осторожность.

Если вы разрабатываете тяжелое JavaScript-приложение и вам нужно беспокоиться об использовании памяти, тогда...

Проблема "грязных" ссылок на объекты, которые приводят к тому, что объекты JavaScript и объекты DOM никогда не собирают мусор, важна для определенных типов приложений JavaScript.Кеши, которые растут вечно, неожиданные глобальные ссылки и неожиданные ссылки внутри замыканий могут быть проблемой.

Может помочь инструмент «Снимок кучи» в Chrome Web Inspector.

Вот пример проекта git, который имеетполезно писать и обходить объекты javascript: https://github.com/tlrobinson/leakhelper

Существуют и другие инструменты, которые могут вам помочь, но я написал свой со временем: 1. наша структура помечает удаленные виджеты, поэтому я написал код для обхода всехмассивы и объекты из окна или документа, ищущие пути к удаленным объектам (код javascript не может пройти замыкания, но он определенно помог найти некоторые утечки).2. Другой трюк, который я использовал, был, когда виджет x был удален, я делаю x.leakhelper = window.createElement ('leakhelper') и setAttribute oid виджета, но не добавляю элемент в документ.Если элемент DOM является , а не собранным мусором, то виджет должен иметь где-то висячую ссылку на него.В IE используйте window.collectGarbage () для принудительной установки GC и используйте sIEve для обнаружения утечек DOM-элемента (я считаю, что sIEve действительно полезен).

Устаревший вопрос: вам нужна сильная поддержка либо IE6, либоIE7 а вы JavaScript активно используете?Большинство страшных утечек, о которых вы читали раньше, происходят только в

1 голос
/ 29 сентября 2011

Это действительно зависит от 2 вещей -

  1. Среднее время выполнения ожидание вашего приложения. Простой лайтбокс jquery или карусель на главной странице интернет-магазина может протекать (и часто это происходит, потому что они так плохо закодированы), но никто не заметит (потому что страница закрыта или обновлена ​​в течение пары минут или меньше). Но сервер Node.js, full-ajax социальная сеть, браузерная игра или онлайн-среда IDE - могут работать часами или даже днями без перерыва.

  2. сложность ввода / вывода вашего приложения. Чем больше вы касаетесь DOM, XHR / сети, файлов, событий DOM / UI, тем больше раз вы перерисовываете экран (будь то canvas, html или svg) - тем больше риск утечек, перебоев в памяти (что НЕ является утечкой) и работает с ошибками браузера.

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

p.s .: если вы должны поддерживать IE8-, вы еще не в 2011 году. Так что вам просто нужно волноваться, как в старые добрые времена .

1 голос
/ 12 сентября 2011

Ну, люди все еще используют старые версии IE.Так что остерегайтесь циклических ссылок, потому что IE имеет серьезные проблемы с этим.Я считаю, что распространенная ошибка в этом отношении - ссылаться на элемент HTML в замыкании, которое находится внутри обработчика события для этого элемента.Просто установите переменную, ссылающуюся на элемент, на null, и все будет хорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...