Всім привіт, шановні колеги! Сьогодні я хотів би поговорити про “легені” Golang - його збирач сміття (GC). Тема, звичайно, давно відома і заїжджена, але оскільки я вже взяв за мету поступово розбирати найважливіші складові мови, то ніяк не міг би пропустити її.

Вступ

Garbage Collector (GC) в Go часто називають "неідеальним" через його відносну простоту, в порівнянні з більш складними реалізаціями в інших мовах програмування, але це зовсім не означає його неефективність для реальних застосунків.

Навпаки, команда розробників мови зробила дуже виважений та обґрунтований вибір на користь простоти реалізації та передбачуваності поведінки, свідомо жертвуючи деякими теоретично можливими оптимізаціями заради створення більш надійної та зрозумілої системи керування пам'яттю.

Як працює GC в Go?

Golang використовує паралельний, трикольоровий Mark-and-Sweep алгоритм. Давайте розберемо більш детально принцип його роботи. Як зрозуміло з назви, цей алгоритм має 2 фази роботи:

  1. Mark Phase - GC позначає всі досяжні об'єкти, використовуючи три кольори: білий, сірий і чорний:
  2. Sweep Phase - видалення всіх білих об'єктів, які залишились після маркування. Ця операція виконується конкурентно із роботою застосунка.

Абстракції та концепції

Stop The World (STW) паузи

Сучасний GC в Go має дуже короткі STW паузи - в середньому <0.5ms для більшості програм. Це досягається завдяки:

Порівняння з іншими мовами

Java (JVM GC): JVM пропонує широкий спектр GC (G1, CMS, Parallel, ZGC, Shenandoah), які часто є набагато складнішими та конфігурованішими. Деякі з них також прагнуть до низької затримки (ZGC, Shenandoah), але зазвичай потребують більше уваги до налаштування. Go GC є простішим за дизайном і менш конфігурованим, з акцентом на "роботу з коробки". Java GC може призводити до довших пауз STW у певних сценаріях, хоча сучасні реалізації значно покращилися.