Cliff Click â CTO of Cratus (IoT sensors for process improvement), founder and co-founder of several startups (including Rocket Realtime School, Neurensic, and H2O.ai) with several successful exits. Cliff wrote his first compiler at the age of 15 (Pascal for TRS Z-80)! He is best known for his work on C2 in Java (the Sea of Nodes IR). This compiler showed the world that JIT can produce quality code, which was one of the factors that established Java as one of the major modern software platforms. Later, Cliff helped Azul Systems build an 864-core mainframe with software in pure Java that supported GC pauses on a 500-gigabyte heap within 10 milliseconds. In fact, Cliff has worked on all aspects of the JVM.
Â
This Habr post is a comprehensive interview with Cliff. We will discuss the following topics:
- Transitioning to low-level optimizations
- How to perform a major refactoring
- Cost model
- Learning low-level optimizations
- Practical examples of performance improvements
- Why create your own programming language
- The career of a performance engineer
- Technical challenges
- A bit about register allocation and multithreading
- The biggest challenge in life
The interviewers are:
- Andrey Satarin from Amazon Web Services. In his career, he has worked on various projects: testing a distributed NewSQL database at Yandex, a cloud detection system at Kaspersky Lab, a multiplayer game at Mail.ru, and a currency pricing service at Deutsche Bank. He is interested in testing large-scale backend and distributed systems.
- Vladimir Sitnikov from Netcracker. He has been working on the performance and scalability of NetCracker OS for ten years â software used by telecommunications operators to automate network management and equipment processes. He is passionate about Java and Oracle Database performance issues. He is the author of more than a dozen performance improvements in the official PostgreSQL JDBC driver.
Transitioning to low-level optimizations
Andrey: You are a well-known person in the world of JIT compilation, Java, and performance work in general, are you not?Â
Cliff: That's right!
Andrey: Let's start with some general questions about performance work. What do you think about the choice between high-level and low-level optimizations such as CPU-level work?
Cliff: Siin on kĂ”ik lihtne. Kiireim kood on see, mis kunagi ei tööta. SeetĂ”ttu tuleb alati alustada kĂ”rge tasemega ja töötada algoritmide kallal. Parema O-mĂ€rgise ĂŒletab halvem O-mĂ€rgise, juhul kui piisavalt suured muutujad ei sekkuma. Madalat taset kĂ€sitletakse viimasena. TĂŒĂŒpiliselt, kui olete kogu ĂŒlejÀÀnud nipi piisavalt hĂ€sti optimeerinud ja on endiselt midagi huvitavat â siis on see madal tase. Kuid kuidas alustada kĂ”rge tasemega? Kuidas teada, et olete kĂ”rgel tasemel piisavalt tööd teinud? No... ei kuidagi. Pole valmis retsepte. Tuleb aru saada probleemist, vĂ€lja selgitada, mida soovite teha (et mitte teha edasisi tarbetuid samme) ja siis saab lahti vĂ”tta profilers, mis vĂ”ib öelda midagi kasulikku. Teatud hetkel mĂ”istate, et olete pÀÀsenud tarbetutest asjadest ning on aeg tegeleda madala taseme tĂ€psustamisega. See on kindlasti eriline kunstivorm. Paljud inimesed teevad tarbetuid asju, kuid edasi liikuda nii kiiresti, et neil pole aega jĂ”udluse pĂ€rast muretseda. Aga see on seni, kuni kĂŒsimus ei tĂ”use esile. TĂŒĂŒpiliselt 99% ajast ei huvita kedagi, millega ma tegelen, kuni kriitilisel teel ei teki olulist asja, mis kellelegi korda lĂ€heb. Ja siis kĂ”ik hakkavad sinult kĂŒsima, âmiks see algusest peale ei töötanud tĂ€iuslikultâ. KokkuvĂ”ttes, alati on midagi, mida jĂ”udluses parandada. Kuid 99% ajast pole sul vihjeid! Sa lihtsalt pĂŒĂŒad midagi töötama panna ja selle kĂ€igus mĂ”istad, mis on oluline. Kunagi ei saa ette teada, et see konkreetne tĂŒkk peab olema ideaalne, seega pead pĂ”himĂ”tteliselt olema ideaalne kĂ”iges. Ja see ei ole vĂ”imalik ning sa seda ei tee. Alati on palju asju, mille kallal töötada â ja see on tĂ€iesti normaalne.
How to perform a major refactoring
Andrey: Kuidas te töötate jĂ”udluse kallal? See on ju ĂŒldine probleem. NĂ€iteks, kas olete pidanud tegelema probleemidega, mis tulenevad suure hulga juba olemasoleva funktsionaalsuse ristumisest?
Cliff: Ma vĂ€ldin seda. Kui ma tean, et jĂ”udlus saab probleemi pĂ”hjuseks, mĂ”tlen ma sellele enne, kui hakkan kodeerima, eriti andmestruktuuride osas. Aga sageli avastad sa kĂ”ik need probleemid liiga hilja. Siis tuleb astuda ÀÀrmuslikke samme ja teha seda, mida ma nimetan 'ĂŒmbersalvestamiseks ja domineerimiseks': tuleb haarata piisavalt suur tĂŒkk. Osa koodist tuleb ikkagi ĂŒmber kirjutada, olgu pĂ”hjuseks jĂ”udluse probleemid vĂ”i midagi muud. ĂkskĂ”ik milline ĂŒmberkirjutamise pĂ”hjus, on peaaegu alati parem ĂŒmber kirjutada suurem tĂŒkk kui vĂ€iksem. Sel hetkel hakkavad kĂ”ik kartma: 'oh jumal, ei tohi nii palju koodi puudutada!'. Kuid tegelikult toimib selline lĂ€henemine peaaegu alati palju paremini. Tuleb kohe haarata suure probleemiga, joonistada selle ĂŒmber suur ring ja öelda: kĂ”ik, mis on ringi sees, ma kirjutan ĂŒmber. Piir on ju palju vĂ€iksem kui see sisu, mis on selle sees, mis tuleb asendada. Ja kui selline piiride joonistamine vĂ”imaldab töö siseselt ideaalselt teha â sul on kĂ€ed vabad, tee, mida iganes soovid. Kui sa oled aru saanud probleemist, lĂ€heb ĂŒmberkirjutamise protsess palju sujuvamalt, seega hammusta suur tĂŒkk!
Samas, kui teed ĂŒmberkirjutamise suure tĂŒki ja mĂ”istad, et jĂ”udlus saab probleemiks, vĂ”id kohe hakata selle pĂ€rast muretsema. Tavaliselt muutuvad need lihtsad asjad, nagu 'Ă€rge kopeeri andmeid, hallake andmeid vĂ”imalikult lihtsalt, tehke neid vĂ€hemaks'. Suurtes ĂŒmberkirjutamistes on standardseid viise, kuidas jĂ”udlust parandada. Ja need keerlevad peaaegu alati andmete ĂŒmber.
Cost model
Andrey: Ăhes teie podkastis rÀÀkisite hindamismudelitest jĂ”udluse kontekstis. Kas saaksite selgitada, mida te selle all silmas pidite?
Cliff: Loomulikult. Ma sĂŒndisin ajastul, mil protsessorite jĂ”udlus oli ÀÀrmiselt oluline. Ja see ajastu naaseb taas â saatusel ei puudunud iroonia. Ma hakkasin elama ajal, mil olid kaheksabitised masinad, minu esimene arvuti töötas 256 baitiga. Just baitidega. KĂ”ik oli vĂ€ga vĂ€ike. Pidi lugema kĂ€ske ja niipea, kui me hakkasime liikuma programmeerimiskeelte virnas ĂŒlespoole, hakkasid keeled endale vĂ”tmisele ĂŒha rohkem ja rohkem. Oli Assembler, siis Basic, siis C, ja C vĂ”ttis enda alla paljusid detaile, nagu registrite ja kĂ€skude jaotamine. Kuid seal oli kĂ”ik ĂŒsna arusaadav ja kui ma tegin nĂ€itaja muutuja eksemplarile, siis sain ma load kĂ€su ja selle kĂ€su hind oli teada. Riistvara annab teada kindla hulga masina tsĂŒkleid, seega vĂ”is erinevate asjade tĂ€itmise kiirus arvutada lihtsalt, liites kĂ”ik kĂ€sud, millele plaanisin kĂ€ivitada. Iga compare/test/branch/call/load/store sai kokku liita ja öelda: siin on tĂ€itmise aeg. Kui tegid jĂ”udluse parandamise nimel tööd, panid kindlasti tĂ€hele, mis numbrid vastavad vĂ€ikestele kuumadele tsĂŒklitele.Â
Aga niipea, kui lĂŒlitad Java, Python ja sarnaste asjade vahel, kaldud vĂ€ga kiiresti eemal madalama taseme riistvarast. Mis on Java getter'i kutsumise hind? Kui JIT HotSpot'is kĂ”ik Ă”igesti , siis on see load, kuid kui ta ei teinud seda â on see funktsiooni kutsumine. Kuna kutse on kuumas tsĂŒklis, tĂŒhistab see kĂ”ik muud optimeerimised selles tsĂŒklis. Seega on tegelik hind palju suurem. Ja sa kaotad kohe vĂ”ime vaadata koodilĂ”iku ja mĂ”ista, kui palju meil tasub seda tĂ€ita protsessori taktsageduse, kasutatava mĂ€lu ja vahemĂ€lu mĂ”ttes. KĂ”ik see muutub huvitavaks, kui tĂ”eliselt sĂŒvened jĂ”udlusesse.
NĂŒĂŒd oleme olukorras, kus protsessorite kiirus pole enam peaaegu kĂŒmme aastat kasvanud. Vanad ajad on tagasi! Te ei saa enam loota heale ĂŒhetuumalisele jĂ”udlusele. Kuid kui teete paralleelseid arvutusi â see on uskumatult keeruline, kĂ”ik vaatavad teid nagu James Bondi. KĂŒmnekordsed kiirused tekivad tavaliselt seal, kus keegi midagi tĂ€helepanuta jĂ€ttis. Paralleelsus nĂ”uab palju tööd. KĂŒmnekordse kiiruskasvu saavutamiseks peate mĂ”istma kulumudelit. Mida ja kui palju see maksab. Ja selleks peate aru saama, kuidas keel sobib alumisele riistvarale.
Martin Thompson leidis oma blogi jaoks suurepĂ€rase sĂ”na. ! On vajalik mĂ”ista, mida riistvara plaanib teha, kuidas see tĂ€pselt seda teeb ja miks see tegelikult seda teeb. Kasutades seda, on ĂŒsna lihtne hakata loendama juhiseid ja aru saama, kuhu tĂ€itmise aeg lĂ€heb. Kui te pole vastava ettevalmistusega, otsite lihtsalt musta kassi pimedas toas. Ma nĂ€en pidevalt inimesi, kes optimeerivad jĂ”udlust, kellel pole vĂ€himatki aimu, mida nad ĂŒldse teevad. Nad vaevavad end vĂ€ga ja ei edene just kuigi palju. Ja kui ma vĂ”tan sama koodi ja lisan sinna paar vĂ€ikest nippi ning saavutavad viiekordse vĂ”i kĂŒmnekordse kiiruskasvu, ĂŒtlevad nad: no, see pole aus, me teadsime ju, et sa oled parem. HĂ€mmastav. Millest see jutt on... kulumudelist â see rÀÀgib sellest, millist koodi te kirjutate ja kui kiiresti see keskmiselt töötab kogu pildis.
Andrey: Ja kuidas sellist mahtu peas hoida? Kas see saavutatakse suure kogemuse kaudu, vÔi? Kust sellist kogemust saada?
Cliff: Noh, oma kogemuse sain ma mitte kĂ”ige lihtsamal viisil. Programmeerisin Assemblers veel siis, kui iga ĂŒksiku juhisega sai tutvuda. See kĂ”lab rumalalt, kuid sellest ajast on mul peas, mĂ€lus, igaveseks jÀÀnud Z80 juhiste komplekt. Ma ei mĂ€leta inimeste nimesid juba minut pĂ€rast vestlust, kuid mĂ€letan 40 aastat tagasi kirjutatud koodi. Huvitav, see nĂ€eb vĂ€lja nagu â».
Learning low-level optimizations
Andrey: Kas on mingi lihtsam viis sisse elada?
Cliff: Jah ja ei. Riistad, mida me kĂ”ik kasutame, pole selle aja jooksul kuigi palju muutunud. KĂ”ik kasutavad x86, vĂ€lja arvatud Armil pĂ”hinevad nutitelefonid. Kui sa ei tegele hardcore-embeddediga, on sul kĂ”ik sama. Hea, jĂ€tkame. Juhised pole samuti sajandeid muutunud. Tuleb minna ja kirjutada midagi Assemblys. Veidi, aga piisavalt, et alustada arvestamist. Sa naeratad, aga ma rÀÀgin tĂ€iesti tĂ”siselt. Pead mĂ”istma keele ja riista vastavust. PĂ€rast seda pead minema ja natuke kirjutama ning tegema vĂ€ikese mĂ€ngu kompilaatori vĂ€ikesele mĂ€ngu keelele. âMĂ€ngeâ tĂ€hendab, et tuleb teha see mĂ”istliku ajaga. See vĂ”ib olla superlihtne, aga peab genereerima juhiseid. Juhiste genereerimise akt aitab mĂ”ista, milline on kulumudel silla ehitamiseks kĂ”rgetasemelise koodi ja masina koodi vahel, mis kĂ€itub riistvaral. See vastavus jÀÀb meelde kompilaatori kirjutamise hetkel. Isegi kĂ”ige lihtsama kompilaatori kirjutamise hetkel. PĂ€rast seda saab hakata vaatama Java keelt ja mille poolest semantiline vahe on palju sĂŒgavam ning kuidas selle ĂŒle on keerulisem sildu ehitada. Java's on palju raskem aru saada, kas meie sild on hea vĂ”i halb, mis viib selle kokkuvarisemiseni ja mis mitte. Aga sul on vaja mingit alust, millega vaadat koodi ja mĂ”ista: âah, see getter peab iga kord inline'ima.â Ja siis selgub, et mĂ”nikord see juhtubki, vĂ€lja arvatud juhul, kui meetod muutub liiga suureks, ja JIT hakkab kĂ”ike jĂ€rjest inline'ima. Selliste kohtade tulemuslikkust saab koheselt ennustada. Ăldiselt töötavad getterid hĂ€sti, aga siis vaatad suuri kuumi sildu ja mĂ”istad, et seal liiguvad mingid funktsiooni kutsed, millel ei ole selge, mida nad teevad. See on probleem getterite laialdases kasutuses, pĂ”hjus, miks nad ei inline'ita â pole selge, kas see on getter. Kui sul on supervĂ€ike koodibaas, saad selle lihtsalt meelde jĂ€tta ja siis öelda: see on getter, aga see on setter. Suures koodibaasis elab iga funktsioon oma lugu, mis ei ole kellelegi kuigi teada. Profilera ĂŒtleb, et oleme kaotanud 24% aega mingis silmus ja et selle silmuse tegevuse mĂ”istmiseks pead vaatama igat funktsiooni sees. Seda on vĂ”imatu mĂ”ista, teadmata funktsiooni, ja see aeglustab tĂ”eliselt arusaamisprotsessi. SeetĂ”ttu ma ei kasuta getterit ja setterit, ma olen jĂ”udnud uuele tasemele!
Kust leida hinnamudelit? No, muidugi vĂ”ib midagi lugeda... Aga ma arvan, et parim viis on tegutseda. Luua vĂ€ike kompilaator ja see on parim viis mĂ”ista hinnamudelit ja panna see oma peadesse. VĂ€ike kompilaator, mis sobiks mikrolaineahi programmeerimiseks â see on algaja ĂŒlesanne. No, ma pean silmas, et kui sul juba on programmeerimisoskused, siis peaks sellest piisama. KĂ”ik need asjad nagu stringi parsimine, mis sul on mingisugune algebraline vĂ€ljend, vĂ”tta sealt vĂ€lja matemaatiliste operatsioonide juhised Ă”iges jĂ€rjekorras, vĂ”tta Ă”iged vÀÀrtused registritest â kĂ”ik see on lihtne. Ja samal ajal, kui sa seda teed, jÀÀb see sinu ajju. Ma arvan, et kĂ”ik teavad, millega kompilaator tegeleb. Ja see annab arusaama hinnamudelist.
Practical examples of performance improvements
Andrey: Millele veel tÀhelepanu pöörata tulemuste parandamise töö kÀigus?
Cliff: Andmestruktuurid. Muide, ma pole ammu neid tunde pidanud... . See oli naljakas, aga nĂ”udis nii palju vaeva, aga mul on ju ka elukĂ€ik! Noh, nii et ĂŒks suur ja huvitav tund, "Kuhu lĂ€heb teie tulemus", andsin ĂŒliĂ”pilastele nĂ€ite: kaks ja pool gigabaiti finantsteabeandmeid loeti CSV-failist ja siis tuli arvestada mĂŒĂŒdavate toodete arvu. Tavalised turuandmed. UDP-paketid, muudetud tekstivormingusse, alates 70ndatest. Chicago Mercantile Exchange â igasugused asjad nagu Ă”li, mais, sojaoad ja nii edasi. Tuli arvestada neid tooteid, tehingute arvu, keskmist rahaliikumist ja kaupu jne. See on ĂŒsna lihtne kaubandusteadus: leida toote kood (see on 1-2 sĂŒmbolit hash-tabelis), saada summa, lisada see ĂŒhe tehingu kogumisse, lisada maht, lisada hind ja paar muud asja. VĂ€ga lihtne matemaatika. MĂ€nguklassi teostus oli vĂ€ga otsekohene: kĂ”ik on failis, ma loen faili ja liigun selle kaudu, jagades ĂŒksikud kirjed Java stringideks, otsin neist vajalikke asju ja liidan vastavalt ĂŒlaltoodud matemaatikale. Ja see töötab mingi vĂ€ikese kiirusaga.
Sellest lĂ€henemisest on kĂ”ik selge, mis toimumas on, ja paralleelsed arvutused ei aita siin, eks? Selgub, et viiekordset jĂ”udluse suurenemist saab saavutada lihtsalt Ă”ige andmestruktuuride valimisega. See ĂŒllatab isegi kogenud programmeerijaid! Minu konkreetses olukorras oli keskpunkt see, et mĂ€lu eraldamine kuumas tsĂŒklis ei ole hea. No, see ei ole kogu tĂ”de, aga ĂŒldiselt â ei tohi eraldada 'iga X' puhul, kui X on piisavalt suur. Kui X on kaks ja pool gigabaiti, siis ei peaks midagi 'iga tĂ€he' vĂ”i 'iga rea' vĂ”i 'iga vĂ€lja' jaoks eraldama, mitte midagi sellist. Just sellele kulubki aega. Kuidas see ĂŒldse töötab? Kujutage ette, et kutsun esile String.split() vĂ”i BufferedReader.readLine(). Readline moodustab stringi andmebaidist, mis on saadetud vĂ”rgu kaudu, igaks read ĂŒhe korra, iga sada miljonit read jaoks. Ma vĂ”tan selle stringi, analĂŒĂŒsin seda et ja viskan Ă€ra. Miks viskan Ă€ra â noh, olen selle juba töötlenud, kĂ”ik. Seega igasuguse byte'i kohta, mis on loetud nendest 2.7G-st, salvestatakse kaks sĂŒmbolit stringis, st juba 5.4G, ja need ei ole mulle enam millekski vajalikud, seega visatakse Ă€ra. Kui vaadata mĂ€lu lĂ€bilaskevĂ”imet, laeme 2.7G, mis lĂ€bib mĂ€lu ja protsessori mĂ€busid, ning seejĂ€rel saadetakse kaks korda rohkem stringiks, mis asub mĂ€lus, ja kĂ”ik see purustatakse iga uue stringi loomise kĂ€igus. Kuid ma pean selle lugema, raud loeb selle, isegi kui seejĂ€rel kĂ”ik purustatakse. Ja ma pean selle kirjutama, sest ma olen loonud stringi ja vahemĂ€lu on tĂ€is - vahemĂ€lu ei saa mahutada 2.7G. Seega igasuguse loetud byte'i kohta loen veel kaks lisabyte'i ja kirjutan kaks lisabyte'i, ja lĂ”puks on nende suhe 4:1 - sellises suhtes raiskame mĂ€lu lĂ€bilaskevĂ”imet. Ja edasi selgub, et kui ma teen String.split() â teen seda kaugel mitte viimast korda, seal sees vĂ”ib olla veel 6-7 vĂ€lja. SeetĂ”ttu toob klassikaline CSV lugemis- ja stringide parsimise kood kaasa mĂ€lu lĂ€bilaskevĂ”ime kadu umbes 14:1 vĂ”rreldes sellega, mida te tegelikult sooviksite omada. Kui need eraldamised Ă€ra visata, siis vĂ”ib saavutada viiekordse kiiruse.
Ja see ei ole ĂŒldse nii keeruline. Kui vaatate koodi Ă”igelt kĂ”rvalt, muutub see ĂŒsna lihtsaks kohe, kui olete probleemist aru saanud. Ei tasu ĂŒldse mĂ€ludelegatsiooni lĂ”petada: probleem on ainult selles, et te jagate mĂ€luruumi ja see sureb kohe, samal ajal pĂ”letades olulist ressurssi, mis antud juhul on mĂ€lu ribalaius. Ja kogu see toob kaasa jĂ”udluse languse. x86 puhul tuleb tavaliselt aktiivselt pĂ”letada protsessoritsĂŒkleid, kuid siin pĂ”letate kogu mĂ€lu palju varem. Lahendus on vĂ€hendada mĂ€ludelegatsioonide arvu.Â
Teine probleem on see, et kui kĂ€ivitada profiler, kui mĂ€lu ribalaius on lĂ”ppenud, just siis, kui see juhtub, siis ootad tavaliselt mĂ€lukahe tagasitulekut, sest see on tĂ€is prĂŒgi, mille just ise genereerisite, kĂ”igi nende ridadega. SeetĂ”ttu iga load vĂ”i store operatsioon muutub aeglaseks, kuna need toovad kaasa mĂ€lukaevu tabamised â kogu vahemĂ€lu muutub aeglaseks, oodates, millal siitĂ€ prĂŒgistas. SeetĂ”ttu nĂ€itab profiler vaid sooja juhuslikku mĂŒra, mis on hajutatud kogu tsĂŒkli ulatuses â ei tule ĂŒhtegi eraldi kuumast instruktsioonist ega koha koodis. Ainult mĂŒra. Ja kui vaatad GC tsĂŒkleid, siis kĂ”ik need on noortele, ja ĂŒlivĂ”imsad â mikrosekundid vĂ”i millisekundid maksimum. Sest kogu see mĂ€lu sureb hetkega. Sa jaotad miljard gigabaiti ja see kĂ€rbib ja kĂ€rbib ning kĂ€rbib jĂ€lle. KĂ”ik see toimub vĂ€ga kiiresti. Saadud tulemuseks on madala hinnaga GC tsĂŒklid, soe mĂŒra kogu tsĂŒkli ulatuses, kuid me soovime saada 5-kordset kiirendust. Sel hetkel peaks midagi olema selge ja kostma: «miks nii?!». MĂ€lu ribalaiuse ĂŒletamine ei kuvata klassikalisest silurist, tuleb kĂ€ivitada riistvara jĂ”udluse arvutite silur ja nĂ€ha seda iseseisvalt ja otse. Ja mitte otse ei saa kahtlustada neid kolme sĂŒmptomit. Kolmas sĂŒmptom on siis, kui vaatad, mida jagad, kĂŒsid profilerilt ja ta vastab: «Sa tegid miljoneid ridu, kuid GC töötas tasuta». Kui see juhtub, saad aru, et moodustasid liiga palju objekte ja pĂ”letad kogu mĂ€lu ribalaiuse. On viis sellest aru saada, kuid see pole ilmne.Â
Andmete struktuuri probleem: alusskeem, mis on kogu toimingu taga, on liiga suur, see on 2,7 G kettal, seetĂ”ttu ei ole selle koopia tegemine soovitatav â soovitakse laadida see otse vĂ”rgu baidipuhvrist registritesse, et mitte lugeda ja kirjutada sinna-sinna viis korda. Kahjuks ei paku Java vaikimisi sellist teeki JDK osana. Kuid see on tĂ”eliselt triviaalne, eks? Sisuliselt on see 5-10 rida koodi, mis viib sellise oma puhverdatud stringi laadija loomise, mis kordab stringiklassi kĂ€itumist, olles samas madalamate baidipuhvrite ĂŒmber. Tulemusena nĂ€ib, et töötad peaaegu nagu stringidega, kuid tegelikult liiguvad seal viidud puhvri nĂ€itajad, ja toored baidid ei kopeerita kuhugi, seega kasutatakse samu puhverid korduvalt, samas kui operatsioonisĂŒsteem on Ă”nnelik selle ĂŒle, et vĂ”tab enda kanda asjad, milleks ta on mĂ”eldud, nĂ€iteks peidetud topeltpuvverdus nende baidipuhvrite puhul, ja sina ise ei purustagi lĂ”putut voolu mittevajalikest andmetest. Muide, kas te mĂ”istate, et GC töötamisel garanteeritakse, et iga mĂ€lu eraldamine ei ole protsessorile nĂ€htav pĂ€rast viimast GC ringi? SeetĂ”ttu ei saa see kĂ”ik kuidagi olla vahemĂ€lus ja edasi toimub 100% garanteeritud möödalaskmine. Viidiku kasutamisel vĂ”tab x86-l registreist mĂ€lu lugemine 1-2 tsĂŒklit ja kohe kui see juhtub, maksad, maksad, maksad, kuna mĂ€lu kĂ”ik on â ja see on mĂ€lu eraldamise hind. Reaalne hind.
TeisisĂ”nu, andmestruktuurid on need, mida on kĂ”ige raskem muuta. Ja kui te olete aru saanud, et olete valinud vale andmestruktuuri, mis tapab tulevikus jĂ”udluse, vajate tavaliselt palju tööd selle parandamiseks; kui seda ei tehta, lĂ€heb asi halvemaks. KĂ”igepealt tuleb mĂ”elda andmestruktuuridele, see on oluline. Peamine kulu seisneb nende rikkaid andmestruktuuride peale, mida hakata kasutama stiilis âma kopeerisin andmestruktuuri X andmestruktuuri Y, sest Y meeldib mulle rohkem kujunduse poolestâ. Kuid kopeerimisoperatsioon (mis tundub odav) kasutab tegelikult mĂ€luressursse ja just siin peitub kogu kadunud tööaeg. Kui mul on hiiglaslik JSON-string ja ma tahan selle muuta struktureeritud DOM-puudeks POJO vĂ”i midagi sarnast, siis selle stringi parseerimise ja POJO ehitamise operatsioon ning hiljem uue pöördumise POJO juurde lisanduvad toimetamis- ja kulud â see ei ole odav. VĂ€lja arvatud juhul, kui te jooksete POJO-d palju sagedamini kui stringide kaudu. Kohapeal vĂ”ib proovida stringi dekodeerida ja sealt ainult vajalik Ă€ra vĂ”tta, ilma et see muudetaks mingiks POJO-ks. Kui kĂ”ik see toimub teel, kus nĂ”utakse maksimaalset jĂ”udlust, mingeid POJO-sid ei ole â peate kuidagi otse stringis kaevama.
Why create your own programming language
Andrey: Te ĂŒtlesite, et kulumudeli mĂ”istmiseks peate kirjutama oma vĂ€ikese keeleâŠ
Cliff: Mitte keel, vaid kompilaator. Keel ja kompilaator on erinevad asjad. Peamine erinevus on teie peas.Â
Andrey: Ăldiselt tean, et eksperimenteerite oma keelte loomisega. Miks?
Cliff: Sest, et saan! Olen poolselt pensionil, nii et see on minu hobi. Olen kogu elu realiseerinud kellegi teise keeli. Ja ma olen palju töötanud kodeerimisstiili kallal. Samuti nĂ€en ma probleeme muudes keeltes. NĂ€en, et on paremaid viise tuttavate asjade tegemiseks. Ja ma kasutan neid. Olen lihtsalt kurnatud, et nĂ€ha probleeme endas, Java's, Pythonis vĂ”i mis tahes muus keeles. Hetkel kirjutan React Native, JavaScripti ja Elmiga hobi korras, mis ei ole pensionile jÀÀmise, vaid aktiivse töö tegemisega seotud. Ja ma kirjutan ka Pythonis ning tĂ”enĂ€oliselt jĂ€tkan masinĂ”ppe arendamist Java-taustade jaoks. Populaarseid keeli on palju ning igalĂŒhel neist on huvitavad omadused. IgaĂŒks on hea millegi poolest ja vĂ”ib proovida nende kĂ”igi nippe kokku viia. Seega, uurin huvitavaid asju, keele kĂ€itumist, pĂŒĂŒan vĂ€lja mĂ”elda arusaadavat semantikat. Ja seni on mul see Ă”nnestunud! Praegu vĂ”itlen mĂ€lu semantika kallal, kuna soovin, et see oleks nagu C ja Java, saavutades tugeva mĂ€lumudeli ja mĂ€lu semantika laadimiste ja salvestuste jaoks. Samuti, et oleks automaatne tĂŒĂŒpide jĂ€reldus nagu Haskellis. Nii et ĂŒritan segada Haskell'i sarnast tĂŒĂŒbi jĂ€reldust mĂ€luga, mis töötab nagu C ja Java. Sellega olen viimased 2-3 kuud tegelenud nĂ€iteks.
Andrey: Kui te ehitate keelt, mis vÔtab teisi keeli parimaid aspekte, kas olete mÔelnud, et keegi teeb vastupidist: vÔtab teie ideed ja kasutab neid enda keeles?
Cliff: Just nii sĂŒnnivad uued keeled! Miks Java sarnaneb C-ga? Sest C-l oli hea sĂŒntaks, mida kĂ”ik mĂ”istsid ja Java sai inspiratsiooni sellest sĂŒntaksist, lisades sinna tĂŒĂŒbikeerukuse, massiivi piiride kontrolli, GC ja nad parandasid ka mĂ”ningaid C omadusi. Nad lisasid omi. Kuid nad said tĂ”eliselt tugevat inspiratsiooni, eks? KĂ”ik seisavad enne sind olnud hiiglaste Ă”lgadel - just nii toimub areng.
Andrey: Nagu ma aru saan, on teie keel mÀlu kasutamise osas ohutu. Kas olete mÔelnud midagi sarnast Rusti borrow checker'ile rakendada? Olete seda vaadanud, kuidas see teile meeldib?
Cliff: Ma olen juba ammu C keeles programmeerinud, kasutades kĂ”iki neid malloc ja free abil mĂ€lu haldamist kĂ€sitsi. Teate, 90-95% kĂ€sitsi haldatud elueast jĂ€rgib sama struktuuri. Ja see on vĂ€ga, vĂ€ga tĂŒĂŒtu, kui seda kĂ€sitsi teha. Tahaks, et kompilaator lihtsalt teataks, mis toimub ja mida olete oma toimingutega saavutanud. MĂ”ned asjad teeb borrow checker seda vaikimisi. Lisaks peaks see automaatselt andma teavet, mĂ”istma kĂ”ike ja mitte koormama mind selle arusaamise edasiandmisega. See peaks teostama vĂ€hemalt kohaliku pĂ”genemisanalĂŒĂŒsi, ja ainult siis, kui see ei Ă”nnestu, tuleks lisada tĂŒĂŒpi annotatsioone, mis kirjeldavad eluea - ja selline skeem on oluliselt keerulisem kui borrow checker vĂ”i mĂ”ni muu olemasolev mĂ€lutest. Valik âkĂ”ik on korrasâ ja âma ei saanud ĂŒldse aruâ â ei, peaks olema midagi paremat.Â
Nii et, inimesena, kes on kirjutanud palju C keeles, arvan, et automaatse elutsĂŒkli halduse tugi on ÀÀrmiselt oluline. Ja veel, mind hĂ€irib, kui palju mĂ€lu Java kasutab ja peamine kaebus on GC. Kui Java-s mĂ€lu eraldatakse, ei tule tagasi mĂ€lu, mis oli kohaliku GC viimases tsĂŒklis. Keeledes, kus mĂ€lu haldus on tĂ€psem, ei ole see nii. Kui kutsud malloc'i, siis saad kohe mĂ€lu, mida tavaliselt just kasutati. Ăldiselt teed mĂ€luga mingid ajutised asjad ja annad kohe tagasi. Ja see naaseb koheselt malloc'i basseinile, ning jĂ€rgmine malloc'i tsĂŒkkel tĂ”mbab selle jĂ€lle vĂ€lja. Seega vĂ€heneb tegelik mĂ€lu kasutamine elavate objektide kogumini konkreetsel hetkel, pluss leke. Ja kui sul ei leki kĂ”ik tĂ€iesti kohutavalt, siis jÀÀb enamus mĂ€lu vahemĂ€ludesse ja protsessorisse, ning see töötab kiiresti. Kuid see nĂ”uab palju kĂ€si mĂ€luhaldust malloc'i ja free abil, mis on kutsutud Ă”igesti Ă”igesse kohta. Rust suudab sellega ise Ă”igesti hakkama saada ja paljudel juhtudel pakkuda isegi suuremat jĂ”udlust, kuna mĂ€lu tarbimine kitseneb ainult praegustele arvutustele â vastupidiselt ootusele, et jĂ€rgmine GC tsĂŒkkel vabastab mĂ€lu. LĂ”ppkokkuvĂ”ttes saime vĂ€ga huvitava viisi jĂ”udluse parandamiseks. Ja ĂŒsna vĂ”imas â mĂ”tlesin, et olen tegelenud selliste asjadega andmete töötlemisel finantstehnoloogias, ning see vĂ”imaldas saavutada kiirusetĂ”usu ligi viie korra. See on ĂŒsna suur kiirusetĂ”us, eriti maailmas, kus protsessorid ei muutu kiiremateks ja me kĂ”ik ootame endiselt tĂ€iustusi.
The career of a performance engineer
Andrey: Samuti tahaksin kĂŒsida karjÀÀri ĂŒldiselt. Te saate tuntuks JIT-i töötamise kaudu HotSpot'is, seejĂ€rel liigutasite Azulisse â ja see on samuti JVM-ettevĂ”te. Kuid tegelesite nĂŒĂŒd rohkem riistvaraga kui tarkvaraga. Ja siis jĂ€rsku pöördusite Big Data ja MasinĂ”ppe poole, seejĂ€rel petuskatsete avastamisele. Kuidas see nii juhtus? Need on vĂ€ga erinevad arenduse valdkonnad.
Cliff: Olen juba ĂŒsna pikka aega programmeerimisega tegelenud ja olen jĂ”udnud paljudele erinevatele tegevustele. Ja kui inimesed ĂŒtlevad: âoh, sina olid see, kes tegi JIT Java jaoks!â, siis see on alati naljakas. Enne seda tegelesin PostScripti klooni loomisega â selle keele, mida Apple kunagi kasutas oma laserprinterites. Ja enne seda tegin Forth keele rakendust. Ma arvan, et minu ĂŒhine teema on tööriistade arendamine. Olen kogu elu teinud tööriistu, millega teised inimesed kirjutavad oma Ă€gedaid programme. Kuid olen tegelenud ka operatsioonisĂŒsteemide, draiverite, tuumadebbugerite, operatsioonisĂŒsteemide arendamiseks mĂ”eldud keelte arendamisega, mis algasid triviaalsetena, kuid aja jooksul muutusid jĂ€rjest keerulisemaks. Kuid pĂ”hiline teema on ikkagi tööriistade arendamine. Suur osa elust möödus Azuli ja Sunny vahel, ja see oli seotud Javaâga. Kuid kui ma hakkasin tegelema suurandmete ja masinĂ”ppega, panin jĂ€lle oma piduliku mĂŒtsi pĂ€he ja ĂŒtlesin: âOh, nĂŒĂŒd on meil keeruline probleem, ja siin toimub palju huvitavaid asju ja inimesi, kes midagi teevad.â See on suurepĂ€rane arengutee, mida tasub lĂ€bida.
Jah, ma armastan tĂ”eliselt hajusalt arvutamist. Minu esimene töö oli ĂŒlikooliajal C keeles reklaamiprojektis. See hĂ”lmas hajusalt arvutamist Zilog Z80 kiipide peal, mis kogusid andmeid analoogsete optiliste tekstide tuvastamiseks, mida tegi tĂ”eline analooganalĂŒsaator. See oli Ă€ge ja tĂ€iesti ebanormaalne teema. Kuid seal olid probleemid, mingi osa ei tuvastatud Ă”igesti, seega tuli vĂ”tta pilt ja nĂ€idata seda inimesele, kes oli juba silmadega lugenud ja teatada, mis seal kirjas on, ja seetĂ”ttu olid seal andmetööd, milles olid oma keel. Oli tagaplaan, mis kĂ”ike seda töötles â paralleelselt töötavad Z80, millel olid aktiivsed vt100 terminalid â igaĂŒhele ĂŒks, ja Z80 ebaĂŒhtne programmeerimisviis. Teatud ĂŒhine mĂ€lutĂŒkk, mida jagasid kĂ”ik Z80 'd konfiguratsioonis âtĂ€htâ; jagati ka tagaplaan ja pool RAM 'ist jagati vĂ”rgus, samas kui teine pool jĂ€i privaatseks vĂ”i lĂ€ks millegi muu jaoks. MĂ”istlikult keeruline paralleelne hajus jaotussĂŒsteem jagatud... osaliselt jagatud mĂ€luga. Millal see juhtus... Ei mĂ€leta isegi, kuskil 80-ndate keskpaiku. Ăsna kaua tagasi.Â
Jah, oletame, et 30 aastat on piisavalt kaua. Hajusalt arvutamisega seotud ĂŒlesanded eksisteerivad piisavalt kaua, inimesed on ammusest ajast selle kallal vaeva nĂ€inud. -klasteritega. Sellised klastrid nĂ€evad vĂ€lja nagu... NĂ€iteks, kui sul on Ethernet ja sinu kiire x86 on sellele Ethernetile ĂŒhendatud, siis soovid nĂŒĂŒd saada vale jagatud mĂ€lu, sest tol ajal ei saanud keegi tegeleda jaotatud arvutamise kodeerimisega, see oli liiga keeruline, ja seetĂ”ttu oli vale jagatud mĂ€lu x86 lehekĂŒlgede kaitsega. Kui sa kirjutasid sellele lehekĂŒljele, siis ĂŒtlesime teistele protsessoritele, et kui nad saavad ligipÀÀsu samale jagatud mĂ€lule, tuleb see sinult laadida. Nii tekkis midagi, mis meenutas vahemĂ€lu jĂ€rjepidevuse protokolli ja selle tarkvara. Huvi pakkuda kontseptsioon. TĂ”eline probleem oli muidugi teises. KĂ”ik see töötas, kuid sa said kiiresti jĂ”udlusprobleeme, sest keegi ei mĂ”istnud jĂ”udlusmudelit piisavalt hĂ€sti â millised olid seal mĂ€lule juurdepÀÀsu mustrid, kuidas teha nii, et node'id ei pingsimoodi ĂŒksteist ei kontrolliks, jne.
H2O-s mĂ”tlesin vĂ€lja jĂ€rgmise: arendajad vastutavad selle eest, et tuvastada, kus paralleelsus on olemas ja kus see puudub. Olen vĂ€lja töötanud kodeerimismudeli, mis lihtsustab kĂ”rge jĂ”udlusega koodi kirjutamist. KĂŒll aga on aeglase toimimisega koodi kirjutamine keeruline ja see nĂ€eb halb vĂ€lja. Aeglase koodi kirjutamiseks tuleb tĂ”siselt pingutada, kasutada tuleb ebatavalisi meetodeid. Aeglaselt toimiv kood on nĂ€ha esimesest pilgust. SeetĂ”ttu kirjutatakse tavaliselt kood, mis töötab kiiresti, kuid tihti tuleb tegeleda jagatud mĂ€lu probleemidega. See kĂ”ik on seotud suurte massiividega ja kĂ€itumine seal sarnaneb mittesĂŒntaktiliste suurte massiividega paralleelses Javas. Kujutage ette, et kaks lĂ”ime kirjutavad paralleelsesse massiivi, ĂŒks neist vĂ”idab ja teine kaotab, kuid te ei tea, kumb on kumb. Kui nad ei ole mittesĂŒnteetilised, vĂ”ib jĂ€rjekord olla mistahes â ja see tĂ”epoolest töötab. Inimesed tĂ”epoolest hoolivad operatsioonide jĂ€rjekorrast, nad paigutavad volatiilseid muutujaid Ă”igesti ja Ă”igetes kohtades ootavad nad mĂ€luga seotud jĂ”udluse probleeme. Vastupidisel juhul kirjutaksid nad lihtsalt koodi tsĂŒklitena 1-st N-ni, kus N on mingid triljonid, lootes, et kĂ”ik keerulised juhtumid muutuvad automaatselt paralleelseks â ja seal see ei toimi. Kuid H2O ei ole ei Java ega Scala, seda vĂ”ib pidada âJava miinus miinusâ, kui tahad. See on vĂ€ga arusaadav programmeerimisstiil ja see sarnaneb lihtsa C vĂ”i Java koodi kirjutamisele tsĂŒklite ja massiividega. Samas saab mĂ€lu hallata terabaitidega. Ma kasutan endiselt H2O-d. Aeg-ajalt kasutan seda erinevates projektides â ja see on endiselt kĂ”ige kiirem lahendus, mis on kĂŒmneid kordi konkurentidest parem. Kui teete Big Data kolonnandmetega, on H2O-d vĂ€ga keeruline ĂŒletada.
Technical challenges
Andrey: Mis on olnud teie suurim vÀljakutse kogu teie karjÀÀri jooksul?
Cliff: Kas arutame tehnilist vĂ”i mitte-tehnilist kĂŒsimust? Ătleksin, et suurimad vĂ€ljakutsed on mitte-tehnilised.Â
Mis tehnilised vĂ€ljakutsed. Ma lihtsalt vĂ”itsin need. Ma isegi ei tea, mis neist kĂ”ige suurem oli, kuid mitu neist olid ĂŒsna huvitavad, mille jaoks kulus palju aega ja vaimset vĂ”itlust. Kui ma tulin Suni, olin kindel, et teen kiire kompilaatori, kuid hulk kogenud spetsialiste kĂŒsis, et mul ei Ă”nnestu kunagi midagi. Kuid lĂ€ksin selle teed, kirjutasin kompilaatori, sealhulgas registreerimisallokaatori, ja see oli ĂŒsna kiire. See oli sama kiire nagu kaasaegne C1, kuid tol ajal oli allokaator palju aeglasem ja tagasi vaadates â see oli probleeme suurte and Structuresiga. Mul oli seda vaja, et kirjutada graafiline registreerimisallokaator, ja ma ei mĂ”istnud dilemma koodi vĂ€ljendusvĂ”ime ja kiirus, mis tollal eksisteeris ja oli vĂ€ga oluline. Selgus, et andmestruktuur ĂŒletab tavaliselt x86 ajal suuruse vahemĂ€lu ja seetĂ”ttu, kui ma algselt arvasin, et registreerimisallokaator töötab 5-10 protsenti kogu JIT-imise ajast, siis tegelikult osutus see 50 protsendiks.
Aeg möödus, kompilaator muutus jĂ€rjest selgemaks ja tĂ”husamaks, lĂ”petas eemaldamise tekitamise halva koodi suuremas osas juhtudel ning tootlikkus hakkas ĂŒha enam meenutama seda, mida C kompilaator pakub. Kui sa muidugi ei kirjuta mingit jama, mida isegi C ei kiirenda. Kui kirjutad koodi nagu C, saad ka tootlikkuse, mis on C sarnane suuremas osas juhtudel. Ja mida kaugemale, seda sagedamini saadud kood oli asĂŒmptootiliselt C tasemetega, registreerimisallokaator hakkas meenutama midagi lĂ”petatut⊠sĂ”ltumata sellest, kas sinu kood töötab kiiresti vĂ”i aeglaselt. JĂ€tkasin allokaatori kallal töötamist, et see teeks paremaid eraldamisi. See muutus jĂ€rjest aeglasemaks, kuid andis ĂŒha paremat tegevust olukordades, kus keegi ei suutnud enam hakkama saada. Ma sain sukelduda registreerimisallokaatorisse, matta sinna kuu töö ja Ă€kitselt hakkas kogu kood töötama 5% kiiremini. See juhtus korduvasti ja registreerimisallokaatorist sai midagi kunstiteose taolist â kĂ”ik armastasid vĂ”i vihkasid seda, ning akadeemia inimesed kĂŒsisid, miks kĂ”ik tĂ€pselt nii tehakse, miks mitte , ja mis on erinevus. Vastus on endiselt sama: graafi vĂ€rvimise pĂ”hine allocator pluss vĂ€ga hoolikas töötamine puhverkoodiga on triumfi relv, parim kombinatsioon, mida keegi ei suuda ĂŒletada. Ja see on ĂŒsna mitteilmne asi. KĂ”ik muu, mida kompilaator seal teeb â on ĂŒsna Ă”ppinud asjad, kuigi need on samuti viidud kunstitasemele. Olen alati teinud asju, mis pidid muutma kompilaatori kunstiteoseks. Kuid midagi sellest ei olnud midagi erakordset â vĂ€lja arvatud registrite allocator. Kinnitatud on see, et tuleb hoolikalt koormuse all ja kui see juhtub (ma vĂ”in selgitada lĂ€hemalt, kui see on huvitav), siis tĂ€hendab see, et saab agressiivsemalt sissetoomist teha, ilma et riskiks suureneda jĂ”udlusgraafi katkestamise ĂŒle. Tol ajal oli palju tĂ€ismahus kompilaatoreid, mis olid ehtitud nipsasjade ja vidinatega, kus olid registrite allocatorid, kuid keegi ei suutnud enam nii teha.
Probleem on see, et kui lisad meetodeid, mis sobivad inlininguks, suurendades ja suurendades inlininguala, siis kasutatavate vÀÀrtuste kogum ĂŒletab kohe registreid ning peab toimuma spilling. Kriitiline tase jĂ”uab tavaliselt kĂ€tte siis, kui allocator annab alla, ja ĂŒks hea kandidaadi spilling viib teise, ning sa spilling mingeid tĂ€iesti kummalisi asju. Inliningu vÀÀrtus seisneb selles, et kaotad osa overheadâist, mis tuleb kutse ja salvestamise peale, sa saad nĂ€ha vÀÀrtusi sees ja saad neid veel optimeerida. Inliningu maksumus seisneb selles, et tekib suur hulk elavaid vÀÀrtusi, ja kui su registri allocator spilling rohkem, kui vajalik, kaotad kohe. SeetĂ”ttu on enamikul allocatoritest probleem: kui inlining lĂ€heb teatud piirist ĂŒle, hakkavad kĂ”ik asjad spilling ja jĂ”udlus vĂ”ib olla kui vette visatud. Need, kes rakendavad kompileerijat, lisavad mĂ”ningaid heuristikat: nĂ€iteks, et peatada inlining, kui see saavutab mingi piisavalt suure suuruse, kuna allocatsioonid rikuvad kĂ”ik Ă€ra. Nii tekib jĂ”udluse graafiku murdumine â sa inliningid, inliningid, jĂ”udlus kasvab vaikselt â ja siis plĂ”ks! â see kukub jĂ€rsku, sest sa oled inlininginud liiga palju. Nii toimis kĂ”ik enne Java saabumist. Java nĂ”uab palju rohkem inliningut, seega pidin oma allocatorit tegema palju agressiivsemaks, et see ei kukuks ja kui sa oled inlininginud liiga palju â hakkab see spillingima, kuid siiski tuleb hetk, mil âenam ei spillingiâ. See on huvitav tĂ€helepanek ja see tuli mulle lihtsalt kuskilt, mitte ilmne, kuid hĂ€sti tasuv. Ma asusin rĂŒndava inlininguga ja see viis mind kohtadesse, kus Java ja C jĂ”udlus kĂ€ivad kĂ”rvuti. Nad on tĂ”eliselt lĂ€hedal â ma saan kirjutada Java koodi, mis on palju kiirem kui C kood, ja nii edasi, kuid keskmiselt, suure pildi kontekstis, on nad ligikaudu vĂ”rdsed. Arvatavasti on osa sellest teenest registri allocator, mis vĂ”imaldab mul inliningida maksimaalselt lolli moodi. Ma inliningin lihtsalt kĂ”ik, mida nĂ€en. KĂŒsimus on selles, kas allocator töötab hĂ€sti, kas tulemusena on mĂ”istlikult töötav kood. See oli suur vĂ€ljakutse: mĂ”ista seda kĂ”ike ja sundida see tööle.
A bit about register allocation and multithreading
Vladimir: Probleemid, nagu registrite jaotamine, tunduvad olema igavene teema. Kas on kunagi olnud nii, et mÔni idee tundus lootustandev, kuid kukkus praktikas lÀbi?
Cliff: Loomulikult! Registrite jaotamine on valdkond, kus NP-tĂ€ieliku probleemi lahendamiseks ĂŒritad leida mingeid heuristikaid. Ja sa ei saa kunagi ideaalsele lahendusele jĂ”uda, eks? See on lihtsalt vĂ”imatu. Vaata, Ahead of Time kompileerimine â see töötab ka halvasti. RÀÀgime siin mingitest keskmistest juhtudest. TĂŒĂŒpilisest jĂ”udlusest, nii et saad minna ja mÔÔta midagi, mida pead heaks tĂŒĂŒpiliseks jĂ”udluseks â lĂ”puks, sa ju töötad selle parandamise nimel! Registrite jaotamine on teema, mis on tĂ€ielikult pĂŒhendatud jĂ”udlusele. Niipea kui sul on esimene prototĂŒĂŒp, mis töötab ja vĂ€rvib, nagu vaja, algab töö jĂ”udluse kallal. Pead Ă”ppima hĂ€sti mÔÔtma. Miks see oluline on? Kui on selged andmed, saad vaadata erinevaid osi ja nĂ€ha: aha, see aitas siin, aga seal lĂ€ks kĂ”ik katki! Tulevad vĂ€lja head ideed, sa lisad uue heuristika ja Ă€kki hakkab kĂ”ik keskmiselt veidi paremini tööle. VĂ”i mitte. Mul oli rohkesti juhtumeid, kus me vĂ”itlesime viie protsendi jĂ”udluse nimel, mis eristas meie arendust eelmisest jaoturist. Ja iga kord nĂ€eb see vĂ€lja nii: kuskil vĂ”itsime, kuskil kaotasime. Kui sul on head jĂ”udluse analĂŒĂŒsi tööriistad, saad leida kaotavad ideed ja mĂ”ista, miks nad kaotavad. VĂ”ib-olla tasub jĂ€tta kĂ”ik nii, nagu on, aga vĂ”ib-olla peaks tĂ”sisemalt jĂ”udluse hÀÀlestamiseks jĂ€rele mĂ”tlema vĂ”i minema ja midagi muud parandama. See on terve hulk asju! Ma tegin selle toreda nippi, aga mulle on vaja ka seda, ja seda, ja seda â ja nende kogusumma toob kaasa teatavaid parandusi. Ja ĂŒksikud vĂ”ivad ebaĂ”nnestuda. Nii see on NP-tĂ€ielike probleemide jĂ”udlusega töötamise loomuses.
Vladimir: Tundub, et asjad nagu jaotajate vĂ€rvimine on juba lahendatud ĂŒlesanne. Noh, teie jaoks lahendatud, arvestades, mida te rÀÀgite, nii et kas siis ĂŒldse tasubâŠ
Cliff: See, it's not solved as such. It's you who must turn it into a 'solved' one. There are hard problems, and they need solving. When that's done, it's time to work on performance. This work needs to be approached appropriately â conduct benchmarks, gather metrics, explain situations where reverting to a previous version made your old hack work again (or vice versa, caused it to stop working). And donât give up until you achieve something. As Iâve said, there are great ideas that didnât work out, but in the realm of register allocation, ideas are practically infinite. For instance, you can read scientific publications. Although this area has started moving much slower now and has become clearer than in its early days. Nevertheless, an entire infinity of people works in this field, and all their ideas are worth trying, they are all waiting for their moment. You can't tell how good they are unless you try them out. How well they integrate with everything else in your allocator, since an allocator does a multitude of things, and some ideas might not work in your specific allocator but could flourish in another. The main way for an allocator to win is to pull the slow stuff out of the main path and force a split across the boundaries of slow paths. So, if you want to trigger GC, take the slow path, deoptimize, throw exceptions, everything in that vein â you know these things are relatively rare. And they really are rare; Iâve checked. You put in extra work, and as a result, numerous constraints on these slow paths disappear, but thatâs not very significant because they are slow and rarely traversed. For example, a null pointer â it never happens, right? You need to have several paths for different things, but they shouldn't interfere on the main one.Â
Vladimir: What do you think about multi-core processing when there are thousands of cores at once? Is it a useful thing?
Cliff: The success of GPUs shows that it's quite beneficial!
Vladimir: They are quite specialized. What about general-purpose processors?
Cliff: Noh, see oli Azul'i Ă€rimudel. Vastus tuli veel ajal, mil inimesed armastasid vĂ€ga prognoositavat jĂ”udlust. Sel ajal oli paralleelse koodi kirjutamine keeruline. H2O kodeerimismudel skaleerub hĂ€sti, kuid see ei ole ĂŒldotstarbeline mudel. Ainult veidi ĂŒldisem kui GPU kasutamisel. Kas me rÀÀgime sellise asja arendamise keerukusest vĂ”i selle kasutamise keerukusest? NĂ€iteks, huvitav Ă”ppetund, mille Azul mulle andis, sai siit: vĂ€ikesed vahemĂ€lud on tĂ€iesti okei.Â
The biggest challenge in life
Vladimir: Ent kuidas on asjadega, mis ei ole tehnilised vÀljakutsed?
Cliff: Suurim vĂ€ljakutse oli mitte olla... lahke ja hea inimeste suhtes. Selle tagajĂ€rjel satun pidevalt ÀÀrmiselt konfliktsetesse olukordadesse. Situatsioonides, kus ma teadsin, et kĂ”ik lĂ€heb valesti, kuid ei teadnud, kuidas edasi liikuda nende probleemide lahendamisel ja ei saanud nendega hakkama. Palju pikaajalisi probleeme, mis kestsid kĂŒmneid aastaid, ilmus just sellisel viisil. See, et Java-s on C1 ja C2 kompilaatorid, on sellest otsene tagajĂ€rg. See, et Java-s ei olnud kĂŒmme aastat mitmeastmelist kompileerimist, on samuti otsene tagajĂ€rg. On tĂ”enĂ€oline, et meil sellist sĂŒsteemi tĂ”eliselt vajasime, kuid pole selge, miks seda ei olnud. Mul olid probleemid ĂŒhe inseneriga... vĂ”i inseneride grupiga. Aastaid tagasi, kui ma hakkasin töötama Sunis, olin ma... Okei, mitte ainult siis, mul on tegelikult alati oma arvamus. Ja ma pean tĂ”eks, et saaks lihtsalt vĂ”tta oma tĂ”e ja öelda seda otse. Eriti arvestades, et mul oli enamikul ajast ĆĄokeerivalt Ă”igus. Ja kui sulle see lĂ€henemine ei meeldi... eriti kui sa oled ilmselgelt vale ja teed rumalusi... Ăldiselt, mitte paljud inimesed ei suutnud sellist suhtlemisviisi taluda. Kuigi mĂ”ned suudavad, nĂ€iteks mina. Olen kogu elu ehitanud meritokraatia pĂ”himĂ”tetele. Kui sa nĂ€itad mulle midagi vale, pöördun ma kohe ringi ja ĂŒtlen: sa ĂŒtlesid rumalust. Sellega loomulikult palun vabandust ja kĂ”ik selline, tunnustan saavutusi, kui neid tĂ”esti on, ja teen teisi Ă”igeid samme. Teiselt poolt, mul on ĆĄokeerivalt palju Ă”igus ĆĄokeerivalt suure osa ajast. Ja see ei mĂ”ju suhetes inimestega hĂ€sti. Ma ei proovi isegi olla armas, vaid panen kĂŒsimuse teravalt ette. âSee ei tööta kunagi, sest pĂ”hjus, kaks ja kolm.â Ja nemad on sellised: âOi!â. Oli ka teisi tagajĂ€rgi, mida oleks parem ilmselt vahele jĂ€tta: nĂ€iteks need, mis viisid lahutuseni oma naisest ja kĂŒmne aasta jooksul kestnud depressioonini pĂ€rast seda.
VĂ€ljakutse on vĂ”itlus inimestega, nende arusaamadega, mida sa saad teha vĂ”i mitte, mis on oluline ja mis mitte. On olnud palju vĂ€ljakutseid koodimistĂŒĂŒbi osas. Ma kirjutan endiselt palju koodi, ja tookord pidin isegi aeglustama, sest tegin liiga palju paralleelseid ĂŒlesandeid ja tegin need halvasti, selle asemel et keskenduda ĂŒhele. Tagasi vaadates kirjutasin ma poole Java JIT meeskonna koodist, C2 meeskonnast. Kiiruselt jĂ€rgmine koodija kirjutas poole aeglasemalt, jĂ€rgmine veel poole aeglasemalt ja see oli eksponentsiaalne langus. Seitsmes inimene selles reas oli vĂ€ga, vĂ€ga aeglane â nii see ikka kipub olema! Ma puutusin kokku hulga koodiga. Ma vaatasin, kes mida kirjutab, ilma eranditeta, uurisin nende koodi, tegin igaĂŒhe ĂŒlevaate ja kirjutasin endiselt rohkem, kui keegi nendest. Inimeste jaoks selline lĂ€henemine ei toimi vĂ€ga hĂ€sti. MĂ”ned ei armasta seda. Ja kui nad ei suuda sellega toime tulla, siis hakkavad igasugused kaebused. NĂ€iteks öeldi mulle kord, et pean lĂ”petama koodi kirjutamise, kuna ma kirjutan liiga palju koodi ja see seab meeskonna ohtu, ja minu jaoks kĂ”las see nagu nalja: kutid, kui kogu ĂŒlejÀÀnud meeskond kaob ja ma jĂ€tkan koodi kirjutamist, kaotad sa ainult poole meeskonnast. Teisest kĂŒljest, kui ma jĂ€tkan koodi kirjutamist ja sa kaotad poole meeskonna â see kĂ”lab vĂ€ga halva juhtimise poolena. Ma ei ole kunagi eriti mĂ”elnud sellele, kunagi sellest rÀÀkinud, aga see oli ikkagi kuskil mu peas. Teadvuse tagahoovis keerles mĂ”te: "Kas te lĂ”butsete vĂ”i?" Seega, kĂ”ige suurem probleem olin mina ja minu suhted inimestega. NĂŒĂŒd mĂ”istan ennast palju paremini, olen pikalt juhtinud programmiere ning nĂŒĂŒd ĂŒtlen otse inimestele: tead, ma olen selline, nagu olen, ja teil tuleb minuga leppida â kas saan siin seista? Ja kui nad hakkasid sellega toime tulema, hakkas kĂ”ik paremini toimima. Ma ei ole tegelikult ei halb ega hea, mul pole mingeid halbu kavatsusi vĂ”i isekaid eesmĂ€rke, see on lihtsalt minu olemus ja sellega tuleb kuidagi elada.
Andrey: Alles hiljuti hakati rÀÀkima eneseteadlikkusest introvertide jaoks ja ĂŒldiselt pehmetest oskustest. Mida selle kohta öelda?
Cliff: Jah, see oli arusaam ja Ă”ppetund, mille ma oma lahutusest naisega sain. Mida ma oma lahutusest Ă”ppisin â see on arusaam enda kohta. Nii hakkasin ma mĂ”istma teisi inimesi. MĂ”istma, kuidas see interaktsioon toimib. See tĂ”i endaga kaasa avastusi jĂ€rjestikku. Ilmnes arusaam, kes ma olen ja mida endast kujutan. Mida ma teen: kas olen mures ĂŒlesande pĂ€rast, vĂ€ldin konflikti vĂ”i midagi muud â ja selline eneseteadlikkuse tase aitab tĂ”eliselt hoida end kontrolli all. PĂ€rast seda lĂ€heb kĂ”ik palju lihtsamalt. Ăks asi, mille ma avastasin mitte ainult enda, vaid ka teiste programmeerijate juures â on vĂ”imetus vĂ€ljendada mĂ”tteid, kui sa oled emotsionaalses stressis. NĂ€iteks istud ja kodeerid, oled voos ja siis jookseb keegi sinu juurde ning hakkab hĂŒsteeriliselt karjuma, et midagi on katki ja nĂŒĂŒd rakendatakse sinule ÀÀrmuslikke meetmeid. Ja sa ei suuda sĂ”nagi öelda, sest oled emotsionaalses stressis. Omandatud teadmised vĂ”imaldavad valmistuda selle hetkeks, seda ĂŒle elada ja liikuda taganemisplaani juurde, pĂ€rast mida on vĂ”imalik midagi ette vĂ”tta. Nii et jah, kui hakkad aru saama, kuidas see kĂ”ik toimib â see on suur elu muutnud sĂŒndmus.Â
Mina ise ei suutnud leida Ă”iged sĂ”nad, kuid mĂ€letan tegevuste jĂ€rjekorda. Ăksikasjalikult on see reaktsioon â fĂŒĂŒsiliselt sama palju kui verbaalselt, ja sul on vaja ruumi. Sellist ruumi, zen-mĂ”ttes. Just seda tuleb seletada ja seejĂ€rel kohe kĂ”rvale astuda â fĂŒĂŒsiliselt kĂ”rvale astuda. Kui ma ei rÀÀgi, saan ma olukorda emotsioonide osas töödelda. Kui adrenaliin jĂ”uab ajju, lĂŒlitab sind see reĆŸiimisse 'löö vĂ”i pĂ”gene', sa ei saa enam midagi rÀÀkida, ei â nĂŒĂŒd oled sa idiot, löömisteks mĂ”eldud insener, kes ei suuda anda vÀÀrilist vastust ega isegi peatada rĂŒnnakut, ja rĂŒndaja saab vabalt uuesti ja uuesti rĂŒnnata. Esiteks pead taas iseendaks saama, taastama kontrolli, vĂ€ljumiseks reĆŸiimist 'löö vĂ”i pĂ”gene'.
Ja selleks on vajalik verbaalne ruum. Lihtsalt vaba ruum. Kui midagi öelda, siis saabki just seda vĂ€ita, ja seejĂ€rel minna tĂ”eliselt leida endale "ruum": jalutada pargis, sulguda duĆĄi alla â pole tĂ€htis. Peamine on ajutiselt end olukorrast eemaldada. Niipea kui sa vĂ€hemalt paariks sekundiks eemaldud, naaseb kontroll, hakkad mĂ”tlema selgelt. "Noh, ma ei ole ju mingi idioot, ma ei tee rumalaid asju, ma olen ĂŒsna kasulik inimene." Niipea kui sa suudad end veenda, on aeg liikuda jĂ€rgmisele etapile: mĂ”ista, mis juhtus. Sulle rĂŒnnati, rĂŒnnak tuli kohast, kust ei oodatud, see oli ebaaus ja kĂŒĂŒniline lĂ”ks. See on halb. JĂ€rgmine samm on mĂ”ista, miks rĂŒndajal seda vajalik oli. TĂ”eliselt, miks? VĂ”ib-olla sellepĂ€rast, et ta ise on vihane? Miks ta on vihane? NĂ€iteks sellepĂ€rast, et ta eksis ja ei saa vastutust vĂ”tta? Nii tuleb hoolikalt kĂ€sitleda kogu olukorda. Kuid selleks on vaja manööverdusruumi, verbaalset ruumi. KĂ”ige esimene samm on katkestada verbaalne kontakt. Eemale minna aruteludest sĂ”nades. TĂŒhistada see, minna minema nii kiiresti kui vĂ”imalik. Kui see on telefonikĂ”ne - lihtsalt pane toru Ă€ra - see on oskus, mille ma sain suhtlemisest oma endise abikaasaga. Kui kĂ”ne ei vii kuskile headesse kohtadesse, lihtsalt ĂŒtle "head aega" ja pane toru Ă€ra. Teiselt poolt toru: "bla-bla-bla", sa vastad: "aha, tĆĄau!" ja paned toru Ă€ra. Lihtsalt katkestad vestluse. Viie minuti pĂ€rast, kui su mĂ”tlemisvĂ”ime naaseb, oled sa natuke jahtunud, on vĂ”imalik mĂ”elda, mis siis ikkagi juhtus ja mis edasi saab. Ja hakata formuleerima mĂ”eldud vastust, mitte lihtsalt reageerida emotsioonidele. Minu jaoks oli lĂ€bimurdeks eneseteadvuses see, et emotsionaalse stressi korral ei suuda ma rÀÀkida. Sellest seisundist vĂ€lja astuda, mĂ”elda ja planeerida, kuidas vastata ja kompenseerida probleeme â need on Ă”iged sammud, kui sa ei saa rÀÀkida. Lihtsaim viis on pĂ”geneda olukorrast, kus emotsionaalne stress ilmneb ja lihtsalt lĂ”petada selles stressis osalemine. PĂ€rast seda saad sa mĂ”elda, kui sa suudad mĂ”elda, tekib vĂ”imalus rÀÀkida ja nii edasi.
Muide, kohtus ĂŒritab vastaspoole advokaat seda sinuga teha â nĂŒĂŒd on juba selge, miks. Sest tal on vĂ”imalus sind nii maha suruda, et sa ei suuda isegi oma nime vĂ€lja öelda, nĂ€iteks. Kirja sĂ”nas mĂ”ttes, sa ei saa rÀÀkida. Kui sinuga juhtub nii ja kui sa tead, et jĂ”uad kohta, kus kĂ€ivad sĂ”nalised lahingud, kohtusse, siis vĂ”ib tulla oma juristiga. Jurist kaitseb sind ja lĂ”petab sĂ”nalise rĂŒnnaku ning teeb seda tĂ€iesti seaduslikul teel, ja sinu kadunud zen-ruum naaseb. NĂ€iteks, mul oli paar korda vaja helistada perele, kohtunik suhtus sellesse ĂŒsna sĂ”bralikult, kuid vastaspoole advokaat karjus ja karjus mulle peale, ma ei saanud isegi sĂ”na vahele öelda. Sellistes olukordades töötab minu jaoks kĂ”ige paremini vahendaja kasutamine. Vahendaja lĂ”petab kogu selle pideva surve, mis sinu peale voolab, sa avastad vajaliku zen-ruumi, koos sellega naaseb ka rÀÀkimisvĂ”ime. See on terve teadmiste valdkond, milles tuleb palju Ă”ppida, palju endas avastada, ja kĂ”ik see muutub kĂ”rgetasemelisteks strateegilisteks otsusteks, mis on erinevad eri inimeste vahel. MĂ”nel inimesel ei ole eespool kirjeldatud probleeme, tavaliselt puuduvad need inimestel, kes tegelevad professionaalselt mĂŒĂŒgiga. KĂ”ik need inimesed, kes teenivad elatist sĂ”nadega â tuntud lauljad, luuletajad, usujuhid ja poliitikud, neil on alati, mida öelda. Neil ei ole selliseid probleeme, kuid mul on need olemas.
Andrey: See oli⊠ootamatu. SuurepÀrane, me oleme juba pÀris palju rÀÀkinud ja on aeg see intervjuu lÔpetada. Me kohtume kindlasti konverentsil ja saame seda dialooge jÀtkata. Kohtume Hydra konverentsil!
JĂ€tkata suhtlemist Cliffiga saab Hydra 2019 konverentsil, mis toimub 11.-12. juulil 2019 Peterburis. Ta tuleb ettekandega . Piletid on saadaval .
Allikas: habr.com
