2009-05-14 5 views
279

Что такое сборка мусора JavaScript? Что важно для веб-программиста понять о сборке мусора JavaScript, чтобы написать лучший код?Что такое сборка мусора JavaScript?

+3

см. Также http://stackoverflow.com/questions/774357/garbage-collection –

+1

см. Также [как работает сборщик мусора javascript?] (Http://stackoverflow.com/q/4324133/1048572) – Bergi

ответ

185

Эрик Липперт написал detailed blog post по этой теме некоторое время назад (дополнительно сравнивая его с VBScript). Точнее, он написал о JScript, который является собственной реализацией Microsoft ECMAScript, хотя очень похож на JavaScript. Я бы предположил, что вы можете предположить, что подавляющее большинство поведения будет одинаковым для движка JavaScript в Internet Explorer. Конечно, реализация будет отличаться от браузера к браузеру, хотя я подозреваю, что вы можете взять несколько общих принципов и применить их к другим браузерам.

Цитируется с этой страницы:

JScript использует nongenerational отметь и выкинь сборщик мусора. Это работает так:

  • Каждая переменная, которая «в рамках» называется «поглотитель». Улавливатель может ссылаться на число, объект, строку , что угодно. Мы сохраняем список плунжеров - переменные перемещаются в список скобок, когда они приходят в область видимости и вне списка scav, когда они выходят за рамки.

  • Время от времени мусор сборщик работает. Сначала он помещает знак « » на каждый объект, переменную, строку , и т. Д. - вся отслеживаемая память от GC. (JScript использует структуру данных VARIANT внутри и есть множество дополнительных неиспользуемых битов в , что структура, поэтому мы просто установить один из них.)

  • Во-вторых, она очищает метку на поглотителей и тому транзитное замыкание ссылок на мусорщик. Поэтому, если объект-поглотитель ссылается на объект noncavenger , то мы очищаем биты на несекундере, а на все, на что оно ссылается. (Я , используя слово «замыкание» в в другом смысле, чем в моем раннем сообщении.)

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

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

Есть несколько конкретных моментов, о которых нужно знать. На сайте разработчика Apple есть some guidelines по этому вопросу. Два важных из них:

  • Использовать инструкции для удаления. Всякий раз, когда вы создаете объект, используя новый оператор, соедините его с инструкцией delete. Это гарантирует, что вся память, связанная с объектом, включая его имя свойства, доступна для сбора мусора. Оператор delete больше обсуждается в разделе «Освобождение объектов».
  • Используйте ключевое слово var. Любая переменная, созданная без ключевого слова var, создается в глобальной области действия и никогда не имеет права на сбор мусора, что дает возможность утечки памяти.

Я предположил бы, что практика должна применяться ко всем двигателям JavaScript (в разных браузерах), хотя, потому что это с сайта компании Apple, они могут быть несколько специфичны для Safari. (Возможно, кто-то может это разъяснить?)

Надеюсь, что это поможет.

+3

+1 отличная ссылка на сайт разработчика яблока –

+4

Ссылка не работает. Кажется, это новое место: http://developer.apple.com/safari/library/documentation/ScriptingAutomation/Conceptual/JSCodingGuide/Advanced/Advanced.html –

+0

@Mark: Спасибо, что указали это. Сообщение обновлено. – Noldorin

1

Что такое сборка мусора JavaScript?

проверка this

Что важно для веб-программист, чтобы понять о сборке мусора JavaScript, для того, чтобы лучше писать код?

В Javascript вы не заботитесь о распределении памяти и освобождении памяти. Вся проблема требует переводчика Javascript. Утечки все еще возможны в Javascript, но они являются ошибками интерпретатора. Если вы заинтересованы в этой теме вы можете прочитать больше в www.memorymanagement.org

+0

Не могли бы вы разрабатывать? – tghw

+0

Какая из различных систем управления памятью в статье, на которую вы ссылаетесь, является той, которая используется JavaScript? _ «Утечки все еще возможны в Javascript, но они являются ошибками интерпретатора». Это не значит, что программисты JS могут просто игнорировать всю проблему, например, есть довольно известный JS <-> DOM круглый справочный вопрос в более старые версии IE, которые вы могли бы использовать в своем JS-коде. Кроме того, способ закрытия JS - это функция дизайна, а не ошибка, но вы можете связать большие куски памяти, чем предполагалось, если вы используете блокировки «ненадлежащим образом» (я не говорю, что не использую их). – nnnnnn

+3

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

51

Остерегайтесь циклических ссылок, когда объекты DOM участвуют:

Memory leak patterns in JavaScript

Имейте в виду, что память может быть восстановлена ​​только тогда, когда нет никаких активных ссылок на объект. Это обычная ошибка с закрытием и обработчиками событий, так как некоторые JS-механизмы не будут проверять, какие переменные на самом деле ссылаются во внутренних функциях, и просто сохранить все локальные переменные входящих функций.

Вот простой пример:

function init() { 
    var bigString = new Array(1000).join('xxx'); 
    var foo = document.getElementById('foo'); 
    foo.onclick = function() { 
     // this might create a closure over `bigString`, 
     // even if `bigString` isn't referenced anywhere! 
    }; 
} 

Наивный реализация JS не может собрать bigString до тех пор, как обработчик события вокруг. Существует несколько способов решить эту проблему, например, установка bigString = null в конце init() (delete не будет работать для локальных переменных и аргументов функции: delete удаляет свойства из объектов, а объект переменной недоступен - ES5 в строгом режиме даже бросает a ReferenceError, если вы попытаетесь удалить локальную переменную!).

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

+19

Круговая справочная ошибка DOM специфична для JScript - ни один другой браузер не страдает, кроме IE.На самом деле, я уверен, что спецификация ECMAScript явно заявляет, что GC должен иметь возможность обрабатывать такие циклы: -/ – olliej

+0

@olliej: Я не вижу упоминания GC в [Спецификации ECMAScript] (http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf). –

+0

см. Также http://point.davidglasser.net/2013/06/27/surprising-javascript-memory-leak.html – Christoph

13

Хорошая цитата взяты из блога

Компонента РОМА «сборка мусора», как компонент JScript, что означает, что если вы создаете объект в любом компоненте, а затем потерять этот объект, его в конечном итоге будет очищен.

Например:

function makeABigObject() { 
var bigArray = new Array(20000); 
} 

При вызове этой функции компонент JScript создает объект (названный BigArray), который доступен в функции. Как только функция возвращается, вы теряете дорожку от bigArray, потому что больше не можете ссылаться на нее. Ну, компонент JScript понимает, что вы его потеряли, и поэтому bigArray очищается - его память исправлена. То же самое происходит в компоненте DOM. Если вы скажете document.createElement('div') или что-то подобное, то компонент DOM создает для вас объект. Как только вы каким-либо образом потеряете этот объект, компонент DOM очистит связанные.

13

Насколько я знаю, объекты JavaScript периодически собираются с мусором, когда на объект не остается никаких ссылок. Это то, что происходит автоматически, но если вы хотите больше узнать о том, как это работает, на уровне C++ имеет смысл взглянуть на WebKit или V8 source code

Обычно вам не нужно об этом думать , однако в более старых браузерах, таких как IE 5.5 и ранние версии IE 6, и, возможно, в текущих версиях, закрытие создаст циклические ссылки, которые, когда unchecked, закончится тем, что съедят память. В частном случае, что я подразумеваю о закрытии, это было когда вы добавили ссылку JavaScript на объект dom и объект для объекта DOM, который ссылался на объект JavaScript. В принципе, он никогда не может быть собран и в конечном итоге приведет к тому, что ОС станет нестабильной в тестовых приложениях, которые зацикливаются на создание сбоев. На практике эти утечки обычно невелики, но чтобы ваш код был чистым, вы должны удалить ссылку JavaScript на объект DOM.

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

+0

Является ли JavaScript -> DOM -> круговой справочной проблемой JavaScript в более новых версиях IE? Если да, то когда? Я думал, что это было архитектурно очень глубоко и вряд ли когда-нибудь зафиксировалось. У вас есть источники? – erikkallen

+0

Просто анекдотически. Я не заметил безумных утечек в IE 8, работающих в стандартном режиме, а не в сломанном режиме. Я отрегулирую свой ответ. –

+1

@erikkallen: да, ошибка GC была исправлена ​​в версиях IE 8+, поскольку более старые использовали очень наивный алгоритм сбора мусора, что сделало невозможным GC пару объектов, ссылающихся друг на друга. Новые алгоритмы стиля «mark-and-sweep» [позаботьтесь об этом] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management). –

3

«В информатике, сбор мусора (GC) является одной из форм автоматического управления памятью. Сборщик мусора, или просто коллекционер, пытается исправить мусор, или память, используемую объектами, которые никогда не будут доступны или мутировавших снова по заявлению ».

Все двигатели JavaScript имеют свои сборщики мусора, и они могут отличаться. В большинстве случаев вам не приходится иметь дело с ними, потому что они просто делают то, что они должны делать.

Написание лучшего кода в основном зависит от того, насколько хорошо вы знаете принципы программирования, язык и конкретную реализацию.

1

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

Это действительно просто, просто введите URL-адрес веб-сайта, и вы увидите потребление памяти встроенного IE-рендерера. Затем нажмите «Обновить», если память увеличится, вы обнаружили утечку памяти где-то на веб-странице. Но также очень полезно увидеть, работают ли программы для освобождения памяти для IE.

6

сбор мусора (GC) - это форма автоматического управления памятью путем удаления объектов, которые больше не нужны.

любая сделка процесс с памятью выполните следующие действия:

1 - выделить ваше пространство памяти вам нужно

2 - сделать некоторые обработки

3 - освободить это пространство памяти

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

подсчет ссылок сбора мусора: этот алгоритм уменьшает определение «объект больше не нужен», чтобы «объект не имеет никакого другого объекта привязки к нему», объект будет удален, если нет опорной точки к нему

Алгоритм пометки и развертки: подключите каждый объект к корневому источнику. любой объект не подключается к корневому или другому объекту. этот объект будет удален.

В настоящее время наиболее современные браузеры используют второй алгоритм.

+1

И чтобы добавить источник этого, см. MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management – Xenos

Смежные вопросы