Вольный перевод - Оригинал Оригинал оригинала
Каждая запущенная js программа представлена выделенной памятью в процессе v8. Эта выделенная память называется Resident Set
, который в свою очередь подразделяется на другие сегменты:
- Resident Set:
- Heap memory:
- New space(Young generation)
- Semi space
- Semi space
- Old space(Old generation)
- Old pointer space
- Old data space
- Large object space
- Code space
- Cell space
- Property cell space
- New space(Young generation)
- Stack
- Heap memory:
HEAP
New space(Young generation)
За очистку этой области памяти отвечает Scavenger(Minor GC), и эта область содержит две области полупростанств (semi space). На размер этих сегментов можно повлиять, указав при запуске nodejs приложения соответсвующие NodeJs флаги:
--min_semi_space_size=size
- Минимальный размер
--max_semi_space_size=size
- Максимальный размер
Old Space
В эту область памяти попадают те объекты из New space, которые пережили 2 цикла Scavenger(Minor GC).
За очистку этой области памяти отвечает Major GC(Mark-Sweep & Mark-Compact). Обычно это самая большая по объему область хипа, ее размер также пожно контролировать соответствующими флагами:
--initial_old_space_size=size
- Начальный размер
--max_old_space_size=size
- Максимальный размер
Old pointer space
Здесь хранятся объекты, которые имеют указатели на другие объекты
Old data space
Здесь хранятся объекты, которые не имеют ссылок на другие объекты, а просто хранят данные: String, boxed numbers, и arrays of unboxed double (TODO: разобраться подробнее про unboxed doubles)
Large object space
Здесь хранятся объекты, которые по размеру превосходят ограничения других сегментов памяти. Сборщик мусора никогда не перемещает большие объекты.
Code-space
Эта область памяти хранит скомпилированные JIT компилятором блоки кода и это единственная область с исполняемой памятью (executable memory), но также куски скомпилированного кода могут быть аллоцированы в Large object space и тогда они тоже будут исполняемыми
Cell-space, property-cell-space and map-space
Каждое из этих простанств содержит объекты (Cells
, PropertyCell
s и Map
) одного размера и имеют ограничения на тип, объекта, на который они могут ссылаться, что упрощает сбор этих объектов.
Каждое из этих простанств состоит из набора Страниц (Pages) - непрерывные чанки памяти, размером 1mb (для Large object space размер может быть больше), которые выделяются операционной системой. Страницы также сожержат различную метаинформацию и битовую карту(bitmap), которая используется, чтобы помечать какие объекты "живы"
STACK
На каждый процесс v8 есть отдельный стек, он хранит указатели на объекты в Heap, Stack frames, примитивы, на размер стека можно повлиять с помощью флага
--stack_size=size
Взаимосвязь Stack и Heap
На этоп презентации наглядно показано, что именно хранится на стеке, а что в куче и в какой момент выполнения кода происходит наполнение и очищение стека (нужно тыкать на стрелочки и вникать в каждый слайд)
https://speakerdeck.com/deepu105/v8-memory-usage-stack-and-heap
Вкратце, происходит следующее:
- Глобальная область видимости хранится в Global Frame
- Каждый вызов функции добавляется в память стека в виде function frame
- Локальные переменные, аргументы и возвращаемые значения также хранятся в function frame
- Все примитивные типы, такие как int и string, хранятся непосредственно в стеке. Это относится и к глобальной области видимости, и да String является примитивным типом JavaScript.
- Все типы объектов, такие как Employee и Function, создаются в куче и на них ссылаются из стека с помощью указателей стека. Функции - это просто вызываемые объекты в JavaScript.
- Функции, вызываемые из текущей функции, кладутся наверх стека
- Когда функция возвращает значение, ее function frame удаляется из стека
- После завершения основного процесса объекты в куче больше не имеют указателей из стека и будут очищены в процессе сбора мусора GC.
- Объекты передаются по ссылке, а не по значению.
TODO: Дополняется...