GoSuda

Go-ajonaikaisen ympäristön kaappaama hetki rauhallisuutta vihreän teen äärellä, GreenTea GC

By snowmerak
views ...

Miksi taas uusi GC on tulossa?

Miksi olemassa oleva GC on olemassa?

Go-kielen nykyinen GC (Garbage Collector) voidaan selittää seuraavilla termeillä:

  • concurrent tri-color mark and sweep (samanaikainen kolmivärinen merkintä ja pyyhkäisy)
    • Se käyttää yhteensä kolmea väriä (valkoinen, harmaa ja musta) objektien tilan seuraamiseen.
      • Valkoinen: Objekti, jota ei ole vielä käsitelty.
      • Harmaa: Objekti, joka on käsitelty, mutta kaikkia sen lapsiobjekteja ei ole vielä käsitelty.
      • Musta: Objekti, jonka kaikki lapsiobjektit on käsitelty.
      • Käsittelyn päätyttyä kaikki valkoiset objektit kerätään.
    • Se käyttää Write Barrieria suojaamaan GC:n aikana vastikään luotua muistia.
      • Aika, joka kuluu Write Barrierin kytkemiseen päälle/pois päältä, on merkittävä osa niin kutsutusta Stop-The-World (jäljempänä STW) -ajasta.
    • Tämä prosessi suoritetaan samanaikaisesti.
  • No Compaction (Ei tiivistämistä)
    • Go:n GC ei suorita tiivistämistä.
    • Muistin pirstaloitumista saattaa tapahtua.
      • Kuitenkin alle 32 kilotavun kokoiset objektit minimoivat pirstaloitumisen hyödyntämällä Go-kielen muistivaraajan (Allocator) per-P-välimuistia.
  • Non-Generational (Ei sukupolvipohjainen)
    • Go:n GC ei hallinnoi objekteja sukupolvittain.
    • Kaikki objektit kuuluvat samaan sukupolveen.
  • Escape Analysis (Pakoanalyysi)
    • Go määrittää Escape Analysisin avulla, allokoituuko objekti keolle vai pinolle.
    • Karkeasti ottaen, jos käytetään riippuvia osoittimia (dangling pointer) tai rajapintoja (interface), voidaan katsoa, että objekti allokoituu keolle.

Tärkeää on

Go:n GC:ssä keskeistä on se, että se etsii kaikki objektit juuresta alkaen ja suorittaa kolmivärisen merkinnän. Tämä prosessi voidaan tiivistää yhdellä rivillä: topologisesti järjestetyn graafin samanaikainen etsintäalgoritmi. Kuitenkin on todennäkööstä, että jokainen objekti sijaitsee eri muistialueilla. Selkeästi sanottuna:

  1. Oletetaan, että meillä on muistialueita, joiden etäisyys toisistaan on noin 32 megatavua.
  2. Näille kahdelle muistialueelle on allokoitu kumpaankin 5 objektia.
    1. Objektit A, B, C ovat alueella 1
    2. Objektit D, E ovat alueella 2
  3. Objektien viittausjärjestys on A -> D -> B -> E -> C.
  4. Kun GC alkaa, se käsittelee A:n, sitten D:n, sitten B:n, sitten E:n ja lopuksi C:n.
  5. Tässä tapauksessa, koska A ja D sijaitsevat eri muistialueilla, muistialuetta on vaihdettava A:n käsittelyn ja D:n käsittelyn välillä.
  6. Tämä prosessi aiheuttaa niin sanottuja muistihyppykustannuksia, kuten muistialueen vaihtamista ja uusien välimuistilinjojen (cache line) täyttämistä. Merkittävä osa sovelluksen käyttämästä suoritinajasta saattaa olla varattu tällaisiin GC-tehtäviin.
  7. Tämä kustannus syntyy jatkuvasti GC:n ollessa käynnissä.

Joten mikä on ongelma?

Tällainen GC:n toiminta on haitallista seuraavissa tapauksissa:

  • Suuri ydinmäärä ja paljon muistia
    • Go:n GC suoritetaan periaatteessa samanaikaisesti.
    • Kuitenkin, jos muistialue on laaja ja objektit ovat hajautuneet, useat ytimet etsivät objekteja samanaikaisesti eri muistialueilla.
    • Jos suorittimen ja muistin välinen väylä ei ole riittävän suuri, muistin kaistanleveys saattaa muodostua pullonkaulaksi.
    • Lisäksi, koska fyysinen etäisyys on olemassa, jokainen etsintä on suhteellisen suuri viive.
  • Paljon pieniä objekteja
    • Jos käytätte Go:ssa syviä tai monilapsisia puita tai graafeja, GC:n on etsittävä kaikki nämä objektit.
    • Jos objektit ovat hajautuneet eri muistialueille, syntyy viivettä ensimmäisen syyn vuoksi.
    • Lisäksi, jos pieniä objekteja on paljon, GC:n on tutkittava ne kaikki, jolloin suoritinytimet varaavat huomattavan määrän kapasiteettiaan GC:lle GC:n suorituksen aikana.

Tämän ongelman ratkaisemiseksi Golang-tiimi on julkaissut GreenTea GC:n.

Sinulla ei ole enää varaa juoda enempää vihreää teetä

Mikä vie vihreän teen pois?

Alue, johon nopein ratkaisu olemassa olevaan GC:hen voitaisiin soveltaa, näyttää olevan muistin lokaalisuus. Toisin sanoen, minimoidaan muistihyppyjä sijoittamalla objektit lähelle toisiaan. Kuitenkaan koodia kirjoittavien ohjelmoijien malleja ei voida pakottaa, ja objektien allokointi on arvaamatonta työnkulun mukaan.

Siksi Golang-tiimin valitsema menetelmä on Memory Span (Muistiväli).

Mikä on Memory Span?

Memory Span on suhteellisen suuri muistialue, joka varataan pienten objektien allokointiin. Ja uusi GC, nimeltään GreenTea GC, suorittaa roskien keruun tällä Memory Span -alueella. Yksityiskohtainen toiminta on lähes identtinen olemassa olevan Tri-Color Mark and Sweep -menetelmän kanssa.

GreenTea GC:n toiminta

Ensiksi GreenTea GC allokoi Memory Spanin. Kuten aiemmin mainittiin, sen koko on huomattava, 8 KiB. Tämän sisällä voidaan allokoida objekteja, joiden koko on enintään 512 tavua. Tämä koko on juuri sellainen, että on vaikea kuvitella puun tai graafin solmukoon, tai yleisen keolle pakenevan rakenteen koon olevan tätä suurempi. Alle 512 tavun kokoiset objektit kertyvät tähän Memory Spaniin aina, kun ne pakenevat keolle, ja kun tämä Memory Span täyttyy, allokoidaan uusi Memory Span.

Kun GC tapahtuu, GreenTea GC kerää nämä Memory Spanit jonoon ja tarkistaa ne peräkkäin. Tässä prosessissa GreenTea GC käyttää lähes samanlaista ajoitusmallia kuin olemassa oleva GMP-malli. Myös työvarastaminen (work stealing) on toteutettu. Joka tapauksessa, työntekijä (worker), joka ottaa Memory Spanin jonosta, tarkistaa sille allokoidun Memory Spanin sisäiset objektit. Tässä prosessissa käytetään samalla tavalla Tri-Color Mark and Sweep -menetelmää.

Mitä hyötyä tästä on?

Ero olemassa olevaan GC:hen tässä prosessissa on pääasiassa vain yksi: GC:n suoritusyksikkö on muuttunut objektista Memory Spaniksi. Tämän seurauksena GC:llä on seuraavat edut:

  • Muistin lokaalisuus: Koska objektit ovat kerääntyneet Memory Spaniin, muistihypyt minimoituvat objekteja etsittäessä. Toisin sanoen, suorittimen välimuistia voidaan hyödyntää maksimaalisesti.
  • GC:n suorituskyvyn paraneminen: Suorittamalla GC Memory Span -yksiköissä, GC toimii tehokkaammin moniydinympäristössä.
  • Muistin allokoinnin optimointi: Koska Memory Span allokoidaan kiinteällä koolla, pienten objektien allokoinnin ylikuormitus vähenee ja pirstaloitumisen mahdollisuus pienenee. Tämä parantaa muistin allokoinnin ja vapauttamisen tehokkuutta.

Lyhyesti sanottuna, voimme nyt allokoida 512 tavun tai sitä pienempiä objekteja useammin ja huolettomammin.

Tässäkin on kuitenkin tiettyjä edullisia skenaarioita.

  • Puu-/graafirakenteet: Kun fan-out on korkea ja muutoksia tapahtuu harvoin
    • B+ puu, Trie, AST (Abstract Syntax Tree)
    • Välimuistiystävälliset tietorakenteet
  • Eräkäsittely: Työnkulut, joissa allokoidaan suuria määriä pieniä datayksiköitä
    • JSON-jäsennyksellä luodut monet pienet objektit
    • Tietokannan tulosjoukon DAO-objektit

Tällaisissa tapauksissa GreenTea GC voi tarjota paremman suorituskyvyn kuin olemassa oleva GC. Sitä ei kuitenkaan sovelleta kaikkiin tapauksiin, ja erityisesti silloin, kun objektit ovat hajautuneet eri muistialueille, dramaattista suorituskyvyn paranemista on edelleen vaikea odottaa.

Joten

Golang-tiimi näyttää olevan aikeissa jatkaa GC:n parantamista pitkällä aikavälillä. Tämä GreenTea GC voidaan nähdä pienimuotoisena muutoksena pienellä alueella, eikä se korvaa olemassa olevaa GC:tä. GreenTea GC vaikuttaa kuitenkin mielenkiintoiselta esimerkiltä, joka antaa kurkistuksen ongelmiin, joita Golang-tiimi kohtaa tai ennakoi. Vaikka ongelma on monimutkainen, yritys ratkaista se suhteellisen yksinkertaisen käsitteen lisäämisellä oli myös vaikuttava. Henkilökohtaisesti pidän tätä mielenkiintoisena tapauksena.

GreenTea GC on kokeellinen ominaisuus, joka otetaan käyttöön Go 1.25:stä alkaen. Sen voi aktivoida käyttämällä ympäristömuuttujaa GOEXPERIMENT=greenteagc. Koska tämä ominaisuus on vielä kokeellinen, riittävä testaus on tarpeen ennen sen käyttöönottoa tuotantoympäristössä.

Viitteet