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

Как устроен garbage collector в Go 1.9 — Андрей Дроздов (Avito)

AvitoTech
October 14, 2017

Как устроен garbage collector в Go 1.9 — Андрей Дроздов (Avito)

Недавно вышел релиз Go 1.9, в нем был обновлен алгоритм сборки мусора. Для того чтобы писать быстрые приложения нужно хорошо понимать как это устроено. В своем докладе я расскажу об алгоритмах сборки мусора и деталях реализации runtime.GC() в Go 1.9 на простых примерах.

Golang Moscow: Встреча в Avito
14/10/2017
https://golang-moscow.timepad.ru/event/587055/

AvitoTech

October 14, 2017
Tweet

More Decks by AvitoTech

Other Decks in Technology

Transcript

  1. Чем мы занимаемся? • BuyerX/Поиск • 35 млн посетителей в

    месяц (~ ¼ Страны) • 38 млн активных объявлений • 1 млн поисковых запросов в минуту 2
  2. О чем я расскажу? • Теория • Как теория GC

    используется в Go • Hacking • Выводы 3
  3. Mark’n’Sweep • Бит достижимости • Изначально все, кроме корневых, не

    размечены Алгоритм: • Останавливаем выполнение • Рекурсивно обходим все объекты и выставляем бит достижимости • Удаляем все недостижимые объекты • Продолжаем работу программы 7
  4. Как же быть? Проблема: Паузы в GC Цель: Пауз не

    должно быть by design Стратегия: GC должен работать полностью отдельно 13
  5. Breath First Mark • Делим все объекты на три группы

    • На каждом шаге помечаем все достижимые объекты как scanned • В “will be scanned” помечаем все, на что есть ссылки • При завершении BFS удаляем все, что не в 1 и второй группе 14
  6. BF Mark. Группы • Black - исследованные объекты • Gray

    - ожидающие исследования объекты • White - неисследованные объекты 15
  7. Почему это работает? • Мы знаем про все объекты в

    памяти • Все, что не попало в 1 и 2 группы, не используется • Следовательно: удаляется только мусор • It works 19
  8. GC Generations 27 • Разделяем объекты на молодые и старые

    • Сканируем с разными интервалами каждую группу • Экономим CPU
  9. Go 1.9 • После релиза 1.8 возникли проблемы вызовом GC

    во время сбора профилей или memory footprint • Для этого библиотечные функции runtime.GC, debug.SetGCPercent, debug.FreeOSMemory были обновлены использованием concurrent GC • Таким образом спайки в latency во время профилирования приложений в production были побеждены mgc.go:1016 34
  10. runtime/mgc* mgc.go - реализация GC mgclarge.go - структура данных (https://en.wikipedia.org/wiki/Treap)

    mgcmark.go - scanner (marking) mgcsweep.go - sweeper (sweeping) mgcsweepbuf.go - buffer/set data structure mgcwork.go - пул GC mbarrier.go - реализация write barrier 36
  11. Состояния GC • GCoff - wb запрещен, проводим sweep в

    фоне • GCMark - wb активен, обходим объекты и размечаем • GCMarkTermination - создаем объекты в черной зоне, wb активен mgc.go:272 37
  12. mgc.go. Фаза Sweep termination • Stop the world • Достижение

    GC safe-point • Завершение всех sweep фаз • Удаление остатков мусора mgc.go:1203 38
  13. mgc.go. Фаза mark 1 • Перевод состояния из GCoff в

    GCMark • Start the world • Новые объекты попадают в черную зону • Обход корневых объектов (стек, глобальные переменные, etc.) • Обработка задач из working pool, обход серой зоны • Найденные указатели помещаются в working pool mgcmark.go:54 39
  14. mgc.go. Фаза mark 2 • Глобальная очередь пуста, локальные очереди

    еще имеют данные • Останавливается работа gc worker’ов • Данные кеша очередей выталкиваются в кеш глобальной очереди • Работа worker’ов продолжается • Продолжается обработка задач из working pool mgc.go:1901 40
  15. mgc.go. Фаза Mark termination • Главная очередь пуста - запускается

    mark termination • Stop the world • Перевод состояния из GCMark в GCMarkTermination • Дообработка последних задач из очереди mgc.go:1458 41
  16. mgc.go. Фаза Sweep • Перевод состояния из GCMarkTermination в GCoff

    • Start the world • Выполнение sweep в фоне mgc.go:1985 42
  17. Интервалы включения GC • Константа GOGC • GC включается при

    увеличении использования памяти на $(GOGC) процентов mgc.go:201 mgc.go:1151 malloc.go:802 43
  18. Community pain • Нет реализации compaction • Нет реализации поколений

    • Не используется весь опыт создания GC • GC не успевает “разгрести” мусор => STW • Триггер запуска GC 46
  19. Выводы • Мы узнали про алгоритмы сборки мусора • Главное

    достижение: STW=const • За GC всегда приходится платить оверхедом • GC - это всегда tradeoff https://gist.github.com/Sulverus/ac9e003124d7a13bee4a7a3f7cb3ae47 49