GoSuda

Go-ajonaikaan (runtime) viedyn vihreän teen hetkellinen rauha: GreenTea GC

By snowmerak views ...

Miksi tarvitaan vielä yksi uusi GC?

Miksi nykyinen GC on sellainen kuin on

Go:n nykyinen GC voidaan kuvata seuraavasti.

  • concurrent tri-color mark and sweep
    • Objektien tilaa seurataan kolmen värin (valkoinen, harmaa, musta) avulla.
      • Valkoinen: objekti, jota ei ole vielä käyty läpi
      • Harmaa: objekti, joka on käyty läpi, mutta jonka lapsiobjekteja ei ole vielä kaikkia käyty läpi
      • Musta: objekti, jonka kaikki lapsiobjektit on käyty läpi
      • Kun läpikäynti päättyy, kaikki valkoiset objektit kerätään.
    • Write Barrier -mekanismia käytetään suojaamaan GC:n aikana uudelleen luotua muistia.
      • Write Barrier -mekanismin kytkeminen päälle ja pois päältä vie suuren osan niin sanotusta Stop-The-World (jäljempänä STW) -ajasta.
    • Tämä prosessi suoritetaan samanaikaisesti.
  • No Compaction
    • Go:n GC ei suorita tiivistämistä (compaction).
    • Muistin pirstoutumista voi tapahtua.
      • Alle 32 kt:n kokoiset objektit kuitenkin minimoivat pirstoutumisen hyödyntämällä Go-kielen muistinvaraajan (Allocator) per-P-välimuistia.
  • Non-Generational
    • Go:n GC ei hallitse objekteja sukupolvittain.
    • Kaikki objektit kuuluvat samaan sukupolveen.
  • Escape Analysis
    • Go käyttää Escape Analysis -menetelmää päättääkseen, allokoidaanko objekti kekoon vai pinoon.
    • Karkeasti ottaen voidaan ajatella, että roikkuvia osoittimia tai rajapintojen käyttöä sisältävät objektit allokoidaan kekoon.

Mikä on tärkeää

Go:n GC etsii kaikki objektit juuresta alkaen ja suorittaa kolmivärisen merkinnän. Tämän prosessin voi ilmaista yhdellä rivillä: topologisen järjestyksen graafin samanaikainen läpikäyntialgoritmi. Objektit sijaitsevat kuitenkin todennäköisesti eri muistialueilla. Yksinkertaisesti sanottuna:

  1. Oletetaan, että on kaksi muistialuetta, jotka ovat noin 32 MB:n etäisyydellä toisistaan.
  2. Kummallekin muistialueelle on allokoitu viisi objektia.
    1. Objektit A, B ja C ovat alueella 1.
    2. Objektit D ja E ovat alueella 2.
  3. Objektien viitejärjestys on A -> D -> B -> E -> C.
  4. Kun GC alkaa, se käy läpi A:n, D:n, B:n, E:n ja C:n tässä järjestyksessä.
  5. Koska A ja D ovat eri muistialueilla, siirtyminen A:sta D:hen edellyttää muistialueen vaihtamista.
  6. Tässä vaiheessa syntyy niin sanottuja muistihyppykustannuksia: muistialuetta vaihdetaan ja uusia välimuistirivejä täytetään. Merkittävä osa sovelluksen käyttämästä suorittimen ajasta voi kohdistua tähän GC-työhön.
  7. Tämä kustannus syntyy jatkuvasti GC:n edetessä.

Mikä siinä on ongelma?

GC:n tämä toimintatapa on erityisen haitallinen seuraavissa tilanteissa.

  • Ytimiä on paljon ja muisti on suuri
    • Go:n GC suoritetaan oletuksena samanaikaisesti.
    • Jos muistialue on laaja ja objektit ovat hajallaan, useat ytimet etsivät objekteja samanaikaisesti eri muistialueilta.
    • Jos suorittimen ja muistin välinen väylä ei ole riittävän leveä, muistin kaistanleveys voi muodostua pullonkaulaksi.
    • Lisäksi fyysinen etäisyys aiheuttaa sen, että jokainen läpikäynti voi viivästyä huomattavasti.
  • Paljon pieniä objekteja
    • Jos ylläpidät Go-kielellä syvä- tai laajahaaraisia puita tai graafeja, GC:n on käytävä kaikki nämä objektit läpi.
    • Jos objektit ovat hajallaan eri muistialueilla, viivettä syntyy ensimmäisen syyn vuoksi.
    • Lisäksi jos pieniä objekteja on paljon, GC:n on käytävä ne kaikki läpi, minkä vuoksi suoritin käyttää GC:hen huomattavan suuren osan kapasiteetistaan GC:n ajon aikana.

Golang-tiimi julkaisi GreenTea GC:n ratkaistakseen nämä ongelmat.

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

Mikä vie vihreän teen

Nopein ratkaisu nykyisen GC:n ongelmiin näyttää kohdistuvan muistin paikallisuuteen (memory locality). Toisin sanoen objektit sijoitetaan lähelle toisiaan, jolloin muistihypyt minimoituvat. Ohjelmoijien kirjoittamia malleja ei kuitenkaan voi pakottaa, eikä objektien allokointia voi ennustaa työnkulusta riippuen.

Niinpä Golang-tiimin valitsema lähestymistapa on muistispani (Memory Span).

Mitä muistispani on?

Muistispani on alue, joka varataan suhteellisen suurena muistialueena ja johon allokoidaan pieniä objekteja. GreenTea GC -nimellä kulkeva uusi GC suorittaa roskienkeruun näille muistispaneille. Yksityiskohtainen toiminta on lähes sama kuin perinteisessä Tri-Color Mark and Sweep -menetelmässä.

GreenTea GC:n toiminta

Ensin GreenTea GC varaa muistispanin. Sen koko on, kuten aiemmin kuvattiin, kohtuullinen 8 KiB. Siihen voidaan allokoida enintään 512 tavun kokoisia objekteja. Juuri esimerkkinä mainittujen puiden tai graafien solmujen koko tai yleisten kekoon siirtyvien rakenteiden koko on tuskin tätä suurempi. Alle 512 tavun objektit kertyvät tähän muistispaniin aina, kun ne siirtyvät kekoon, ja kun spani täyttyy, varataan uusi muistispani.

Kun GC käynnistyy, GreenTea GC asettaa nämä muistispanit jonoon ja tarkistaa ne peräkkäin. Tässä prosessissa GreenTea GC käyttää ajoituksessa lähes samaa mallia kuin nykyinen GMP-malli. Myös työn varastamisen (work stealing) kaltainen toiminta on toteutettu. Joka tapauksessa jonosta muistispanin ottanut työntekijä tarkistaa sille osoitetun muistispanin sisäiset objektit. Tässä prosessissa käytetään samaa Tri-Color Mark and Sweep -menetelmää.

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

Tässä prosessissa ero nykyiseen GC:hen on karkeasti ottaen yksi: yksittäinen GC-operaation yksikkö on muuttunut objektista muistispaniksi. Tämän vuoksi GC:llä on seuraavia etuja.

  • Muistin paikallisuus: Koska objektit ovat koottuina muistispaniin, muistihypyt minimoituvat objektien läpikäynnin aikana. Toisin sanoen suorittimen välimuistia voidaan hyödyntää mahdollisimman tehokkaasti.
  • GC:n suorituskyvyn parantaminen: Suorittamalla GC muistispanin yksikössä GC toimii tehokkaammin monisydämisessä ympäristössä.
  • Muistin allokoinnin optimointi: Koska muistispanit varataan kiinteän kokoisina, pienten objektien allokoinnin ylikuormitus pienenee ja pirstoutumisen mahdollisuus vähenee. Tämä parantaa muistin vapauttamisen tehokkuutta.

Lyhyesti sanottuna: tästä eteenpäin voimme allokoida alle 512 tavun objekteja useammin ja vapaammin mielin.

Tietyissä tilanteissa tämä on kuitenkin jossain määrin edullista.

  • Puu- ja graafirakenteet: korkea haarautumisaste ja vähäiset muutokset
    • B+-puut, Trie, AST (Abstract Syntax Tree)
    • Välimuistiystävälliset tietorakenteet
  • Erätyöstö: suuri määrä pieniä datan allokointeja
    • Suuri määrä pieniä objekteja, jotka syntyvät JSON-jäsennyksessä
    • Tietokantatulosjoukon DAO-objektit

Näissä tapauksissa GreenTea GC voi saavuttaa paremman suorituskyvyn kuin nykyinen GC. Se ei kuitenkaan sovellu kaikkiin tilanteisiin, ja erityisesti silloin, kun objektit ovat hajallaan eri muistialueilla, dramaattisen suorituskykyparannuksen odottaminen on edelleen vaikeaa.

Joten

Golang-tiimillä on todennäköisesti aikomus kehittää GC:tä pitkällä aikavälillä. GreenTea GC on tulkittavissa pienen alueen pieneksi muutokseksi, eikä se korvaa nykyistä GC:tä. GreenTea GC on kuitenkin kiinnostava esimerkki siitä, mitä ongelmia Golang-tiimi kohtaa tai odottaa. Ongelma on yllättävän monimutkainen, mutta yritys ratkaista se suhteellisen yksinkertaisella käsitteellä vaikutti minusta vaikuttavalta. Henkilökohtaisesti pidän sitä mielenkiintoisena tapauksena.

GreenTea GC on kokeellinen ominaisuus, joka otetaan käyttöön Go 1.25:stä alkaen. Sen voi ottaa käyttöön asettamalla ympäristömuuttujan GOEXPERIMENT=greenteagc. Koska ominaisuus on vielä kokeellinen, sitä on testattava perusteellisesti ennen käyttöä tuotantoympäristössä.

Viitteet