2015-04-23 2 views
0

Учитывая типичную структуру, как показано ниже, когда есть различные переменные Освободившись сборщик мусором ?:Private переменных памяти распределение

'Use strict'; 

var $ = require('jquery'); 
var somePrivateVar = new Whatever(); 

module.exports = functions(){ 
    var someInsideVar = new Whatother(); 
    var someOtherInsideVar = $('.myStuf'); 
    $(window).scroll(function(){ 
     somePrivateVar.MoreStuff(); 
     doSomeStuff(someInsideVar); 
     someOtherInsideVar.toggle(); 
    }); 
}; 

Редакция: Предлагаемый другой вопрос связан, но не точки этого вопрос. Я уже немного знаю о сборке мусора. Меня не интересует обработка мусора или его устранение. Меня интересует, как nodejs монтирует модули за кулисами. Другими словами, если вам нравится, как nodejs реализует эти принципы в первом ответе на другой вопрос, чтобы эффективно обрабатывать память.

+0

@MarcoBonelli - Этот возможный дубликат - это всего лишь общий вопрос/ответ на сборщик мусора и не затрагивает и не объясняет, что этот вопрос задает вообще о переменных уровня модуля в node.js. – jfriend00

+0

Я редактировал вопрос. Кроме того, я не сказал этого, но он был неявным. Я хотел бы получить конкретный ответ в этом конкретном сценарии, а не общий ответ на копирование-вставку из теории GC. Было бы неплохо пояснить сроки. Также не забывайте о жизни обработчиков событий. Они влияют на это? – Adminiculo

ответ

1

Модуль в node.js - это просто закрытие, которое остается живым по тем же правилам, что и другие закрытия в Javascript останутся в живых. Пока какой-либо код в закрытии по-прежнему доступен другому коду, тогда сам затвор не может быть собранным мусором. И модули также кэшируются загрузчиком модуля, что означает, что ссылка на модуль сохраняется в кеше модуля, даже если никакой другой код не сохранил ссылку на модуль. Вы можете счесть полезным прочитать эту статью: How require() Actually Works, потому что это обычный Javascript GC области действия, которая определяет, когда данный модуль может быть собран с помощью мусора. Для модулей нет специальной сборки мусора.

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

По умолчанию модуль узла остается в живых и загружен в кеш-модуль узла (ожидание чего-то еще в require()), даже если оно больше не используется или не упоминается остальной частью вашего кода. Его можно вручную удалить из кеша, если вы этого захотите. См. Этот ответ для подробностей о том, как вручную удалить модуль (и, возможно, любые модули, которые он также загружает) из кеша: Unloading node code/modules. Итак, если ни один из ваших кодов не имеет ссылки на модуль, в модуле нет обработчиков событий или обратных вызовов в нем, и вы вручную удалили модуль из кеша, тогда закрытие модуля больше не должно иметь ссылок на доступный код в он и GC могут освободить весь объем (и, следовательно, модуль).

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

В вашем конкретном примере, обработчик $(window).scroll() события (который, кажется, как-то вроде составил пример, потому что там обычно нет window объекта в Node.js, что делает прокруткой) теоретически быть вечно живым, пока вы вручную удалили обработчик события с .off() или до window сам объект удаляется или что-то в этом роде. Таким образом, ссылки внутри этого обработчика событий никогда не исчезнут сами по себе.

Другие обработчики событий, имеющие определенный срок службы, такие как обработчик успеха Ajax, будут выполнены, когда сам вызов ajax завершит выполнение, и все обратные вызовы были вызваны. Эти обработчики событий будут выпускать любые ссылки, которые они хранят, когда они будут выполнены. То же самое для setTimeout(). Он будет освобождать любую ссылку, которую он держит, когда он выполняется (или когда таймер отменяется).

Часто бывает трудно предсказать, насколько разумным может быть сборщик мусора, и когда он поймет, что данная переменная больше недоступна и, следовательно, может быть собрана мусор. Некоторые вещи легко понять, например, когда переменная выходит за пределы области действия, и никакие другие ссылки не остаются в области видимости, поэтому вся область будет GCed. Но некоторые вещи не так просты, например, когда область видимости еще жива, потому что обработчик событий в этой области все еще жив, но ничто в этом конкретном обработчике событий не может действительно ссылаться на данную переменную в этой области. Независимо от того, будет ли GC фактически пытаться использовать GC в одной переменной в этой области, в этом случае зависит от реализации. Такие вещи, как eval() и создание новых объектов с кодом, созданным с помощью строковых манипуляций, очень усложняют Javascript, чтобы точно знать, что можно и не может ссылаться в будущем от данного обработчика события или обратного вызова (поскольку можно построить почти любую ссылку программно без переводчика, зная, что вы «можете» ссылаться в будущем). Это усложняет мелкозернистую сборку мусора. На что вы можете рассчитывать - это сборка мусора всего объема (когда выпущена вся область действия). Рассчитывая на более мелкозернистый GC, чем это, вероятно, неразумно. Если вы выполняете операцию с очень большой переменной в пределах области действия, которая может длиться намного дольше, тогда более безопасно только null из этой очень большой переменной, поэтому ее конкретная ссылка на большие данные очищается, когда вы хотите ее очистить. Это не было бы значительным для небольшой строки (если у вас не было десятков тысяч этих объектов), но может иметь значение для большого буфера или очень большой строки.


Edit: Это действительно кажется, что V8 делает сбор мусора отдельных переменных в пределах области, если сами эти переменные не ссылаются в любой код, который все еще достижимы в закрытии и нет использования eval() в том же коде. Я не нашел никаких авторитетных ссылок на эту тему, но подтвердил, что это происходит в случае тестирования реальных ситуаций.

+0

Пожалуйста, определите 'module alive'. Скажем, вы используете этот модуль без назначения, просто вызывая его «require (« mymodule »);». Он жив только до окончания выполнения запроса или остается в живых до тех пор, пока назначены обработчики для событий? – Adminiculo

+0

@Adminiculo - я добавил более подробную информацию. – jfriend00

+0

Теперь это очень хороший ответ. В частности, я не знал о кэше модулей nodejs. Благодарю. – Adminiculo

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