---
id: a5d668f7af98fc92ee33094885d591a3
author: snowmerak
title: Pohoda s čajom zelenej, ktorú Go runtime nevezme, GreenTea GC
description: Nový GreenTea GC v jazyku Go zlepšuje výkon tým, že na základe pamäťových spanov zvyšuje efektivitu GC pri malých objektoch. Pozrieme sa na problémy existujúceho GC a na výhody GreenTea GC.
language: sk
date: 2025-07-16T11:02:04.831022221Z
path: /blog/posts/greentea-gc:-the-respite-of-a-cup-of-green-tea-seized-by-the-go-compiler-z72acc3f7
category: lowlevel
---

## Prečo vzniká ďalší nový GC?

### Prečo existujúci GC

Súčasný GC jazyka Go možno opísať nasledujúcimi pojmami.

- concurrent tri-color mark and sweep
  - Na sledovanie stavu objektov sa používajú tri farby (biela, sivá, čierna).
    - Biela: objekt, ktorý ešte nebol navštívený
    - Sivá: objekt, ktorý bol navštívený, ale nie všetky jeho podriadené objekty
    - Čierna: objekt, ktorého všetky podriadené objekty boli navštívené
    - Po ukončení prechodu sa všetky biele objekty uvoľnia.
  - Write Barrier sa používa na ochranu pamäte, ktorá vzniká počas GC.
    - Čas zapnutia a vypnutia Write Barrier tvorí značnú časť takzvaného Stop-The-World (ďalej len STW).
  - Tento proces sa vykonáva súbežne.
- No Compaction
  - GC jazyka Go nevykonáva kompaktáciu.
  - Môže dochádzať k fragmentácii pamäte.
    - Objekty do 32 kB však využívajú per-P cache alokátora pamäte jazyka Go, čím sa fragmentácia minimalizuje.
- Non-Generational
  - GC jazyka Go nespravuje objekty podľa generácií.
  - Všetky objekty patria do rovnakej generácie.
- Escape Analysis
  - Go pomocou Escape Analysis rozhoduje, či sa objekt alokuje na halde alebo na zásobníku.
  - Zhruba možno povedať, že ak sa používajú visiace ukazovatele alebo rozhrania, objekt sa alokuje na halde.

### Čo je dôležité

GC jazyka Go prechádza všetky objekty od koreňov a vykonáva tri-farebné označovanie. Tento proces možno v jednom riadku opísať ako `súbežné prehľadávanie grafu v topologickom poradí`. Jednotlivé objekty sa však pravdepodobne nachádzajú v rôznych oblastiach pamäte. Stručne povedané:

1. Predpokladajme, že existujú dve oblasti pamäte vzdialené približne 32 MB.
2. V každej z týchto oblastí je alokovaných 5 objektov.
   1. Objekty A, B, C sú v oblasti 1
   2. Objekty D, E sú v oblasti 2
3. Poradie referencií objektov je `A -> D -> B -> E -> C`.
4. Keď sa GC spustí, navštívi A, potom D, potom B, potom E a nakoniec C.
5. Keďže A a D sa nachádzajú v rôznych oblastiach pamäte, pri návšteve A a následne D je potrebné prejsť medzi oblasťami pamäte.
6. Tento proces spôsobuje takzvanú cenu skoku v pamäti, pretože dochádza k prechodu medzi oblasťami a k napĺňaniu nových cache riadkov. Značná časť času CPU, ktorý využíva aplikácia, môže byť pridelená týmto úlohám GC.
7. Táto cena vzniká nepretržite počas celého behu GC.

### Aký je v tom problém?

Správanie tohto GC je problematické v nasledujúcich prípadoch.

- Veľký počet jadier a veľká pamäť
  - GC jazyka Go sa v zásade vykonáva súbežne.
  - Ak je však pamäťová oblasť rozsiahla a objekty sú rozptýlené, viacero jadier súčasne prehľadáva objekty v rôznych častiach pamäte.
  - Ak nie je zbernica medzi CPU a pamäťou dostatočne široká, šírka pásma pamäte sa môže stať úzkym miestom.
  - Keďže ide o fyzicky vzdialené miesta, každé jednotlivé prehľadanie môže spôsobiť relatívne veľké oneskorenie.
- Veľké množstvo drobných objektov
  - Ak prevádzkujete v jazyku Go stromy alebo grafy s veľkou hĺbkou alebo s mnohými potomkami, GC musí prehľadať všetky tieto objekty.
  - Ak sú tieto objekty rozptýlené v rôznych oblastiach pamäte, oneskorenie vzniká z dôvodu uvedeného v prvom bode.
  - Navyše, ak je drobných objektov veľa, GC musí prehľadať všetky tieto objekty, a preto počas behu GC bude veľká časť výkonu jadier CPU pridelená GC.

Na riešenie týchto problémov tím Golang predstavil GreenTea GC.

## Už nemáte čas na ďalší zelený čaj

### Čo odoberá zelený čaj

Zdá sa, že najrýchlejším riešením existujúceho GC sa javí lokalita pamäte. To znamená umiestniť objekty blízko seba, aby sa minimalizovali skoky v pamäti. Programátorom však nemožno vnútiť vzorce písania kódu a alokácia objektov závisí od pracovného postupu, takže sa nedá predvídať.

Tím Golang preto zvolil prístup **Memory Span (pamäťový rozsah)**.

### Čo je Memory Span?

Memory Span je miesto, kde sa z relatívne veľkej pridelenej pamäťovej oblasti alokujú malé objekty. Nový GC s názvom GreenTea GC vykonáva zber odpadu práve nad týmito pamäťovými rozsahmi. Podrobné správanie je takmer rovnaké ako pri existujúcom Tri-Color Mark and Sweep.

### Činnosť GreenTea GC

GreenTea GC najskôr alokuje Memory Span. Jeho veľkosť je, ako bolo uvedené vyššie, 8 KiB, čo je dostatočne veľká hodnota. Do neho možno alokovať objekty s veľkosťou najviac 512 bajtov. Veľkosť uzla stromu alebo grafu, o ktorom sme hovorili, alebo štruktúry bežne unikajúcej na haldu, sa len ťažko dá predstaviť ako väčšia než táto hodnota. Objekty do 512 bajtov sa pri každom úniku na haldu ukladajú do tohto Memory Span a keď je Memory Span plný, alokuje sa nový.

Keď nastane GC, GreenTea GC zaradí tieto Memory Span do fronty a kontroluje ich postupne. Pri tom GreenTea GC používa plánovanie, ktoré je takmer rovnaké ako existujúci model GMP. Je implementovaná aj oblasť krádeže práce. Worker, ktorý z fronty vyberie Memory Span, kontroluje objekty vo svojom pridelenom Memory Span. Pritom sa rovnako používa Tri-Color Mark and Sweep.

### Aký je z toho prínos?

V tomto procese je rozdiel oproti existujúcemu GC v podstate jediný. Jednotka, pre ktorú sa GC vykonáva naraz, sa zmenila z **objektu** na **Memory Span**. Vďaka tomu má GC nasledujúce výhody.

- Lokalita pamäte: Keďže objekty sú sústredené v Memory Span, pri prehľadávaní objektov sa minimalizujú skoky v pamäti. To znamená, že sa dokáže maximálne využiť CPU cache.
- Zlepšenie výkonu GC: Vykonávaním GC po jednotkách Memory Span funguje GC efektívnejšie vo viacjadrovom prostredí.
- Optimalizácia alokácie pamäte: Memory Span sa alokuje s pevnou veľkosťou, preto sa pri alokácii malých objektov znižuje réžia alokácie a klesá pravdepodobnosť fragmentácie. To zvyšuje efektivitu uvoľňovania pamäte.

Stručne povedané, od tejto chvíle môžeme častejšie a s ľahším srdcom alokovať objekty do 512 bajtov.

Aj tu však existujú isté výhodné oblasti.

- Štruktúry stromov/grafov: Prípady s vysokým fan-outom, kde sa štruktúra často nemení
  - B+ stromy, Trie, AST (Abstract Syntax Tree)
  - Dátové štruktúry priateľské k cache
- Dávkové spracovanie: pracovné postupy s hromadnou alokáciou malých dát
  - Viaceré malé objekty vytvorené pri parsovaní JSON
  - DAO objekty z výsledných množín databázy

V týchto prípadoch môže GreenTea GC dosiahnuť lepší výkon než existujúci GC. Nie je však vhodný pre všetky prípady a najmä ak sú objekty rozptýlené v rôznych oblastiach pamäte, stále nemožno očakávať dramatické zlepšenie výkonu.

## Takže

Zdá sa, že tím Golang má pravdepodobne zámer GC dlhodobo ďalej zlepšovať. Tento GreenTea GC možno považovať za drobnú zmenu v malej oblasti a nenahrádza existujúci GC. GreenTea GC však predstavuje zaujímavý príklad, ktorý napovedá o problémoch, ktorým tím Golang čelí alebo ktoré predvída. Ide o prekvapivo zložitý problém, no pokus o jeho riešenie pridaním relatívne jednoduchého konceptu bol pôsobivý. Osobne ho považujem za zaujímavý prípad.

GreenTea GC je experimentálna funkcia, ktorá sa zavádza od Go 1.25. Aktivuje sa nastavením premennej prostredia `GOEXPERIMENT=greenteagc`. Keďže táto funkcia je stále experimentálna, pred nasadením v produkčnom prostredí je potrebné dôkladné testovanie.

## Referencie

- [github.com/golang/go - runtime: green tea garbage collector #73581](https://github.com/golang/go/issues/73581)
