memory in v8

Вольный перевод - Оригинал Оригинал оригинала

Каждая запущенная 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
    • Stack

resident-set.png

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, PropertyCells и 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: Дополняется...