Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Garbage collection in V8 engine (RU slides)

Garbage collection in V8 engine (RU slides)

Sasha (Oleksandr) Syrotenko

November 16, 2017
Tweet

More Decks by Sasha (Oleksandr) Syrotenko

Other Decks in Programming

Transcript

  1. Кто я такой? • Студент факультета кибернетики КНУ им. Шевченка.

    • Пишу на C++, Java/Scala/Kotlin(JVM) и JS(V8). • Люблю копаться в движках и писать фронтенд. 2
  2. Кто я такой? • Студент факультета кибернетики КНУ им. Шевченка.

    • Пишу на C++, Java/Scala/Kotlin(JVM) и JS(V8). • Люблю копаться в движках и писать фронтенд. • Компиляторов, если что. 2
  3. GC в V8 • Как и во всех виртуальных машинах,

    существует система управления памятью : 5
  4. GC в V8 • Как и во всех виртуальных машинах,

    существует система управления памятью : • Аллокатор. 5
  5. GC в V8 • Как и во всех виртуальных машинах,

    существует система управления памятью : • Аллокатор. • Сборщик мусора (он же GC). 5
  6. Модель памяти в JS (V8) 6 • Все остальные объекты,

    аллоцирующиеся в хипе, неявно наследуются от HeapObject. • Все объекты выровнены на 4 байта. • Отдельно представлены целые числа на стеке
  7. Как устроен Heap • New Space (aka YoungGen): Большинство объектов

    живут именно здесь. Умирают тоже. 7
  8. Как устроен Heap • New Space (aka YoungGen): Большинство объектов

    живут именно здесь. Умирают тоже. • Old Space (aka OldGen) : Объекты, пережившие одну и больше фаз сборки. 7
  9. Как устроен Heap • New Space (aka YoungGen): Большинство объектов

    живут именно здесь. Умирают тоже. • Old Space (aka OldGen) : Объекты, пережившие одну и больше фаз сборки. • Code Space: Здесь размещаются объекты кода, содержащие инструкции JIT-компилятора. Это единственное пространство с исполняемой памятью. 7
  10. Слабая гипотеза о поколениях • Объекты чаще всего не переживают

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

    в V8), позволяет разработчикам виртуальных машин делать некоторые спекулятивные операции. 10
  12. Внезапная польза • Подобная гипотеза, подтвержденная частыми наблюдениями (не только

    в V8), позволяет разработчикам виртуальных машин делать некоторые спекулятивные операции. • А именно - разделять сборки в регионах хипа, и разрабатывать разные алгоритмы для них. 10
  13. Подходы к сборке • Stop-the-world (город main-thread приложения засыпает, GC

    работает, после окончания приложение опять просыпается). 11
  14. Подходы к сборке • Stop-the-world (город main-thread приложения засыпает, GC

    работает, после окончания приложение опять просыпается). • Concurrent (сборщик (частями) работает параллельно с приложением). 11
  15. Подходы к сборке • Stop-the-world (город main-thread приложения засыпает, GC

    работает, после окончания приложение опять просыпается). • Concurrent (сборщик (частями) работает параллельно с приложением). • Важно : конкурентными могут быть несколько из фаз сборки! 11
  16. Стратегии сборки Всего существует аж 3 стратегии сборки мусора :

    • No operations: считаем все объекты мусором, и творим тотальный экстерминатус всем обитателям хипа, вырубая работающую VM. 12
  17. Стратегии сборки Всего существует аж 3 стратегии сборки мусора :

    • No operations: считаем все объекты мусором, и творим тотальный экстерминатус всем обитателям хипа, вырубая работающую VM. • Mark-Sweep/Compact: помечаем все живые объекты, удаляем недостижимые (и делаем перемещение живых регионов). 12
  18. Стратегии сборки Всего существует аж 3 стратегии сборки мусора :

    • No operations: считаем все объекты мусором, и творим тотальный экстерминатус всем обитателям хипа, вырубая работающую VM. • Mark-Sweep/Compact: помечаем все живые объекты, удаляем недостижимые (и делаем перемещение живых регионов). • Pointer counting: присобачиваем к каждому объекту счетчик ссылок на него и удаляем его, когда счетчик равен нулю. 12
  19. Немного недоумения • Вообще-то, настоящим, на мой вкус, сборщиком мусора,

    является подход с подсчетом ссылок. • В Mark-* мы помечаем и перемещаем достижимые объекты, а не мусор! 13
  20. Сборка в YoungGen • Два субрегиона : «From Space» и

    «To Space» • «From Space» изначально пустой. 14
  21. Сборка в YoungGen • Два субрегиона : «From Space» и

    «To Space» • «From Space» изначально пустой. • К GC прилетел сигнал, что в «To Space» переполнение. 14
  22. Сборка в YoungGen • Два субрегиона : «From Space» и

    «To Space» • «From Space» изначально пустой. • К GC прилетел сигнал, что в «To Space» переполнение. • Также существует специальный Pointer Map на все объекты из Young Generation. 14
  23. Scavenger, Part 1 1. To Space переполнился*, GC начинает работу.

    2. To Space и From Space обмениваются своим содержимым. 15
  24. Scavenger, Part 2 3. Проходимся линейно по From Space, помечаем

    живые объекты. 4. Перемещаем живые объекты в To Space, удаляем лишнее из From Space. 16
  25. Scavenger, Part 2 3. Проходимся линейно по From Space, помечаем

    живые объекты. 4. Перемещаем живые объекты в To Space, удаляем лишнее из From Space. 5. To Space отдает эти данные в OldGen. 16
  26. Сборка в OldGen Сборка в OldGen является классическим алгоритмом Mark-Compact:

    1. Сначала, начиная из rootset, проходимся по всему графу объектов и помечаем достижимые. (Mark*) 17
  27. Сборка в OldGen Сборка в OldGen является классическим алгоритмом Mark-Compact:

    1. Сначала, начиная из rootset, проходимся по всему графу объектов и помечаем достижимые. (Mark*) 2. Чистим хип. (Sweep) 17
  28. Сборка в OldGen Сборка в OldGen является классическим алгоритмом Mark-Compact:

    1. Сначала, начиная из rootset, проходимся по всему графу объектов и помечаем достижимые. (Mark*) 2. Чистим хип. (Sweep) 3. Сжимаем хип. (Compact) 17
  29. Стадия : Mark Алгоритм маркировки представляет собой (главным образом) обход

    графа в глубину с использованием стека и трехцветной абстракцией : 18
  30. Стадия : Mark Алгоритм маркировки представляет собой (главным образом) обход

    графа в глубину с использованием стека и трехцветной абстракцией : • Черные - вершины с посещенными и просканированными ссылками. 18
  31. Стадия : Mark Алгоритм маркировки представляет собой (главным образом) обход

    графа в глубину с использованием стека и трехцветной абстракцией : • Черные - вершины с посещенными и просканированными ссылками. • Серые - посещенные вершины с непросмотренными ссылками. 18
  32. Стадия : Mark Алгоритм маркировки представляет собой (главным образом) обход

    графа в глубину с использованием стека и трехцветной абстракцией : • Черные - вершины с посещенными и просканированными ссылками. • Серые - посещенные вершины с непросмотренными ссылками. • Белые - непосещенные вершины. 18
  33. Стадия : Mark Алгоритм маркировки представляет собой (главным образом) обход

    графа в глубину с использованием стека и трехцветной абстракцией : • Черные - вершины с посещенными и просканированными ссылками. • Серые - посещенные вершины с непросмотренными ссылками. • Белые - непосещенные вершины. Используется стек указателей, а не рекурсия. (Привет, StackOverflow), и им является From Space из YoungGen. 18
  34. Incremental Mark 31 • Начинается, когда куча становится больше некоего

    порогового значения, а не заполняется. • Пауз становится больше, но они становятся короче.
  35. Incremental Mark 31 • Начинается, когда куча становится больше некоего

    порогового значения, а не заполняется. • Пауз становится больше, но они становятся короче. • За паузу сканируется часть хипа.
  36. Incremental Mark 31 • Начинается, когда куча становится больше некоего

    порогового значения, а не заполняется. • Пауз становится больше, но они становятся короче. • За паузу сканируется часть хипа. • Но взамен на эту всю красоту появляются проблемы с консистентностью графа объектов.
  37. 32 Incremental Mark : трабла раз Аллоцирование нового объекта в

    черном объекте / указание ссылки на «мусорный» объект.
  38. 35 Write Barriers • Существует специальный буфер, в который помещаются

    перехваченные записи в хип. • Удаления при этом обрабатываются. 
 То есть, удаленные ссылки не считаются удаленными до конца текущей раскраски объектов. После они спокойно удаляются.
  39. 37 Порешаем траблы А давайте-ка покрасим родителя зеленой ссылки в

    серый, и снова пройдемся по его дочерним объектам и ссылкам. ОПЯТЬ РАБОТАТЬ?
  40. 38 Порешаем траблы А давайте-ка покрасим родителя зеленой ссылки в

    серый, и снова пройдемся по его дочерним объектам и ссылкам.
  41. 39 Порешаем траблы А давайте-ка покрасим родителя зеленой ссылки в

    серый, и снова пройдемся по его дочерним объектам и ссылкам.
  42. 40 Порешаем траблы А давайте-ка покрасим родителя зеленой ссылки в

    серый, и снова пройдемся по его дочерним объектам и ссылкам.
  43. 41 Порешаем траблы Готово! 
 И да, это не настолько

    дорого, как Вы подумали.
 Эвристики нам в помощь :)
  44. Стадия : Sweep • Sweep чрезвычайно прост: он просто выполняет

    линейный поиск мёртвых объекты в каждой странице хипа, очищает память, и передает ее в специальный список свободной памяти. 42
  45. Стадия : Sweep • В каждой странице хранятся отдельные списки

    свободной памяти для небольших регионов (< 2^8 слов), средние регионы (< 2^11 слов), большие регионы (< 2^14 слова) и огромные регионы. 43
  46. Стадия : Sweep • В каждой странице хранятся отдельные списки

    свободной памяти для небольших регионов (< 2^8 слов), средние регионы (< 2^11 слов), большие регионы (< 2^14 слова) и огромные регионы. • Свободные списки в основном используются алгоритмом Scavenge для перемещения выживших объектов в OldGen, a также используются алгоритмом уплотнения для перемещения объектов. 43
  47. Sweep наглядно 46 Фаза третья. В каждом регионе sweeper удалил

    объекты и отдал память под повторную аллокацию.
  48. Parallel Sweep • Так как хип размечен по регионам, выделить

    N-ное количество потоков на уборку этих самых регионов не составляет труда. 47
  49. Parallel Sweep • Так как хип размечен по регионам, выделить

    N-ное количество потоков на уборку этих самых регионов не составляет труда. • Время паузы при этом заметно сокращается. 47
  50. Стадия : Compact • Самая сложная, на мой вкус, функция

    сборщика мусора. • Главная проблема здесь - обеспечить дефрагментацию страниц. 48
  51. Стадия : Compact • Самая сложная, на мой вкус, функция

    сборщика мусора. • Главная проблема здесь - обеспечить дефрагментацию страниц. • Порождает N-нное количество головняка у разработчиков GC. 48
  52. Как справился Google? • Google может выдохнуть, так как на

    самом деле JS не является многопоточным, и большое количество нюансов, которые надо предусмотреть в многопоточной среде языка, исчезают. • Но перенос внутри VM все равно происходит в критической секции.
  53. Compact крупно • Compact переносит объекты из фрагментированных регионов (содержащих

    много небольших свободных пространств) в свободные места на других регионах. 50
  54. Compact крупно • Compact переносит объекты из фрагментированных регионов (содержащих

    много небольших свободных пространств) в свободные места на других регионах. • Для каждого живого объекта в эвакуируемом регионе выделяется место из списка свободной памяти другой страницы. 50
  55. Compact крупно • Compact переносит объекты из фрагментированных регионов (содержащих

    много небольших свободных пространств) в свободные места на других регионах. • Для каждого живого объекта в эвакуируемом регионе выделяется место из списка свободной памяти другой страницы. • Каждый объект копируется в выделенное место, а в еще не удаленном объекте появляется так называемый «forwarding pointer», указывающий на настоящий объект. 50
  56. Перенос объектов 59 Как только эвакуация завершена, V8 выполняет итерацию

    по списку записанных мест указателя и обновляет их, указывая на новые копии.
  57. После уборки • Все объекты снова маркируются как «белые». •

    GC прибирается в кэшах и деоптимизрует отмеченные для деоптимизиации объекты. • Отпускает паузу. 62
  58. Выводы • Гуглу удалось создать коллектор, который балансирует между средним

    временем паузы и оверхэдом на сборку. При этом разработчики (большинство) довольны, так как у них не возникает с ним проблем. • Если уж приложение и тормозит, то вам стоит покопаться в собственном коде и посмотреть на вкладку «Performance», и проверить, а поэтому ли тормозит? • Если да, то попросить приложение меньше мусорить. 63