Suur intervjuu Cliff Clickiga — Java JIT-kompilaatori isa

Suur intervjuu Cliff Clickiga — Java JIT-kompilaatori isaCliff Click — Cratus'i CTO (IoT-sensorid protsesside parandamiseks), mitme idufirma (sealhulgas Rocket Realtime School, Neurensic ja H2O.ai) asutaja ja kaasasutaja, kellel on olnud mitu edukat vĂ€ljajÀÀmist. Cliff kirjutas oma esimese kompilaatori 15-aastaselt (Pascal TRS Z-80 jaoks)! Ta on kĂ”ige tuntum oma töö poolest C2 puhul Java-s (the Sea of Nodes IR). See kompilaator nĂ€itas maailmale, et JIT suudab toota kvaliteetset koodi, mis aitas kaasa Java kujunemisele ĂŒheks peamiseks tĂ€napĂ€evaseks tarkvaraplatvormiks. Hiljem aitas Cliff Azul Systems'il ehitada 864 tuuma mĂ€safraimi puhtale Java-le, mis toetas GC-pause 500 GB kuhjaga 10 millisekundiga. Üldiselt on Cliff töötanud JVM-i kĂ”igi aspektide kallal.

 
See postitus on suur intervjuu Cliffiga. RÀÀgime jÀrgmistest teemadest:

  • Üleminek madala taseme optimeerimisele
  • Kuidas teha suurt refaktoreerimist
  • Kulude modelleerimine
  • Madala taseme optimeerimise Ă”petamine
  • Praktilised nĂ€ited jĂ”udluse parandamisest
  • Miks luua oma programmeerimiskeel
  • Performantsiinseneri karjÀÀr
  • Tehnilised vĂ€ljakutsed
  • Veidi registri ja multi-tuumade jaotamisest
  • Elu suurim vĂ€ljakutse

Intervjuud viib lÀbi:

  • Andrei Satariin Amazon Web Servicesist. Oma karjÀÀri jooksul on ta töötanud tĂ€iesti erinevates projektides: testinud Yandexis jaotatud NewSQL andmebaasi, Kaspersky Labis pilveseire sĂŒsteemi, Mail.ru-s mitme kasutajaga mĂ€ngu ja Deutsche Bankis valuutahindade arvutamise teenust. Ta on huvitatud suuremahulisest backend- ja jaotatud sĂŒsteemide testimisest.
  • Vladimir Sitnikov Netcrackerist. Töötab ĂŒle kĂŒmne aasta NetCracker OS'i jĂ”udluse ja skaleeritavuse kallal — tarkvara, mida sideoperaatorid kasutavad vĂ”rgu juhtimise ja seadmete haldamise automatiseerimiseks. Huvitub Java ja Oracle Database jĂ”udlusest. On autoriks enam kui kĂŒmnele jĂ”udluse parandusele ametlikus PostgreSQL JDBC-draivis.

Üleminek madala taseme optimeerimisele

Andrei: Te olete tuntud JIT-kompileerimise, Java ja ĂŒldiselt jĂ”udluse valdkonnas, eks? 

Cliff: Just nii!

Andrei: Alustame ĂŒldiste kĂŒsimustega jĂ”udluse töötlemise kohta. Mida arvate madala taseme ja kĂ”rge taseme optimeerimise valiku vahel, nĂ€iteks CPU tasemel töötamisest?

Cliff: Siin on kĂ”ik lihtne. Kiireim kood on see, mis kunagi ei kĂ€ivitu. SeetĂ”ttu tuleb alati alustada kĂ”rge tasemega, töötada algoritmide kallal. Paremini kirjutatud O-notation ĂŒletab halvemini kirjutatud O-notation, vĂ€lja arvatud juhul, kui sekkuda mĂ”ned piisavalt suured konstandid. Madala taseme asjad tulevad kĂ”ige viimasena. Tavaliselt, kui oled optimeerinud kogu ĂŒlejÀÀnud stack'i piisavalt hĂ€sti ja midagi huvitavat on ikka veel jÀÀnud – see ongi madal tase. Kuidas alustada kĂ”rge taseme juurest? Kuidas teada, et olete teinud piisavalt tööd kĂ”rgel tasemel? No... ei kuidagi. Valmis retsepte ei ole. Tuleb probleemi lahendada, otsustada, mida plaanid teha (et mitte teha edaspidi tarbetu sammud) ja siis saab vĂ€lja vĂ”tta profailer, mis suudab öelda midagi kasulikku. Mingil hetkel saad sa ise aru, et oled vabanenud tarbetutest asjadest ja on aeg madala taseme tĂ€psustamisega tegeleda. See on kindlasti eriline kunstivorm. Palju inimesi teeb tarbetuid asju, aga liigub nii kiiresti, et neil ei ole aega tootlikkuse pĂ€rast muretseda. Kuid see on seni, kuni kĂŒsimus ei tĂ”use Ă€kitselt ĂŒles. Tavaliselt 99% ajast ei huvita kedagi, millega ma tegelevad, kuni kriitilisel teel ei seisa mingi oluline asi, mis kellelegi korda lĂ€heb. Ja siis hakkavad kĂ”ik sind kiusama, et «miks see alguses ei töötanud ideaalselt». Üldiselt on alati midagi, mida perfformantsi osas paremaks teha. Aga 99% ajast pole sul mingeid vihjeid! Sa lihtsalt proovid saada midagi tööle ja selle kĂ€igus saad sa aru, mis on oluline. Kunagi ei saa ette teada, et just see tĂŒkk tuleb teha ideaalseks, seega tuleb pĂ”himĂ”tteliselt olla ideaalne igas asjas. Ja see on vĂ”imatu ja sa ei tee nii. Alati on palju asju, mis vajavad parandamist – ja see on tĂ€iesti normaalne.

Kuidas teha suurt refaktoreerimist

Andrei: Kuidas te töötate jÔudluse nimel? See on tÔepoolest keeruline probleem. NÀiteks, kas olete pidanud tegelema probleemidega, mis tulenevad suure hulga juba olemasoleva funktsionaalsuse ristumiste tÔttu?

Cliff: Ma vĂ€ldin seda. Kui ma tean, et jĂ”udlus saab probleemiks, siis mĂ”tlen sellele enne, kui hakkan kodeerima, eriti andmestructuuride osas. Kuid sageli avastad sa kĂ”ik selle alles hiljem. Ja siis pead vĂ”tma ÀÀrmuslikke meetmeid ning tegema seda, mida ma nimetan 'ĂŒle kirjutama ja valitsema': pead haarama piisavalt suure osa. Osa koodist tuleb nagunii nĂ€iteks jĂ”udlusprobleemide vĂ”i muude pĂ”hjuste tĂ”ttu ĂŒmber kirjutada. Mis iganes pĂ”hjus ka ĂŒmberkirjutamisel ei oleks, on peaaegu alati parem ĂŒmber kirjutada suurem tĂŒkk kui vĂ€iksem tĂŒkk. Sel hetkel hakkavad kĂ”ik kartma: 'oh jumal, ei tohi nii palju koodi puutuda!'. Aga tegelikult, see lĂ€henemine töötab peaaegu alati palju paremini. Pead kohe haarama suure probleemi, joonistama selle ĂŒmber suure ringi ja ĂŒtlema: kĂ”ik, mis on ringi sees, kirjutan ĂŒmber. Piir on ju palju vĂ€iksem kui see sisu, mis on selle sees asendamisele mÀÀratud. Ja kui selline piiride mÀÀratlemine vĂ”imaldab teha tööd seal sees ideaalselt – sul on kĂ€ed vabaks, tee, mida tahad. Kui sa oled probleemi mĂ”istnud, siis lĂ€heb ĂŒmberkirjutamisprotsess palju lihtsamaks, seega hammusta suur tĂŒkk!
Samas, kui teed suurt ĂŒmberkirjutamist ja mĂ”istad, et jĂ”udlus hakkab probleemiks saama, tasub kohe selle pĂ€rast muretseda. See muutub tavaliselt lihtsate asjadeks nagu "Ă€rge kopeerige andmeid, haldage andmeid nii lihtsalt kui vĂ”imalik, tehke need vĂ€iksemaks". Suurte ĂŒmberkirjutamiste puhul on olemas standardmeetodid, et jĂ”udlust parandada. Need keskenduvad enamasti andmetele.

Kulude modelleerimine

Andrei: Ühes podcastis rÀÀkisite hinnamudelitest jĂ”udluse kontekstis. Kas saaksite selgitada, mida selle all silmas pidite?

Cliff: Muidugi. Ma sĂŒndisin ajastul, kus protsessori efektiivsus oli ÀÀrmiselt oluline. Ja see ajastu naaseb — saatus pole ilma irooniata. Ma alustasin elu kaheksabitiste masinatega, minu esimene arvuti töötas 256 baitiga. Just baiti. KĂ”ik oli vĂ€ga vĂ€ike. Oli vaja lugeda kĂ€ske ja kui me hakkasime liikuma kĂ”rgemate programmeerimiskeelte poole, vĂ”tsid keeled endaga jĂ€rjest rohkem ja rohkem tööd. Oli Assambleerimine, siis Basic, seejĂ€rel C, ja C vĂ”ttis enda peale palju detaile, nagu registrite ja kĂ€skude jaotamine. Kuid seal oli kĂ”ik ĂŒsna arusaadav ja kui ma tegin nĂ€itaja muutuja eksemplarile, sain ma laadimise ja selle kĂ€su hind oli teada. Riistvara annab vĂ€lja kindla arvu masina tsĂŒkleid, nii et erinevate asjade tĂ€itmise kiirus oli vĂ”imalik lihtsalt kokku lugeda, liites kĂ”ik kĂ€sud, mida sa kavatsesid kĂ€ivitada. Iga compare/test/branch/call/load/store sai kokku liita ja öelda: siin on sinu tĂ€itmise aeg. Ainult efektiivsuse parandamisega tegeledes pöörad kindlasti tĂ€helepanu numbritele, mis vastavad vĂ€ikestele kuumadele tsĂŒklitele. 
Kuid niipea, kui sa lĂŒlitud Java, Python ja sarnaste asjade juurde, eemaldud sa kiiresti madalamast tasemest. Milline on getteri kutse maksumus Javas? Kui JIT HotSpot'is kĂ”ik Ă”igesti inline'itud, siis on see laadimine, kuid kui ta seda ei teinud – on see funktsioonikutse. Kuna kutse asetub kuumasse tsĂŒklisse, tĂŒhistab see kĂ”ik muud optimeeringud selles tsĂŒklis. SeetĂ”ttu on tegelik maksumus palju suurem. Ja sa kaotad kohe vĂ”ime vaadata koodijuppi ja mĂ”ista, kui palju peaksime selle tĂ€itmiseks arvestama protsessori taktsageduse, kasutatud mĂ€lu ja vahemĂ€lu osas. KĂ”ik see muutub huvitavaks ainult siis, kui sĂŒvened tĂ”eliselt jĂ”udlusesse.
Praegu oleme olukorras, kus protsessorite kiirus ei ole viimase kĂŒmne aasta jooksul oluliselt muutunud. Vanad ajad naasevad! Te ei saa enam loota heale ĂŒhetuumalisele jĂ”udlusele. Kuid kui te siiski tegelete paralleelsete arvutustega – on see ÀÀrmiselt keeruline, kĂ”ik vaatavad teid nagu James Bondi. KĂŒmnekordsed kiirusetĂ”usud ilmnevad tavaliselt seal, kus keegi midagi ei mĂ€rka. Paralleelsus nĂ”uab palju tööd. Et saavutada see kĂŒmnekordne kiirusetĂ”us, peate mĂ”istma vÀÀrtusmudelit. Mis on ja kui palju see maksab. Selleks peate mĂ”istma, kuidas keel sobitub alumisele riistvarale.
Martin Thompson leidis oma blogile suurepĂ€rase sĂ”na Mehaaniline kaastunne! Peab aru saama, mida riistvara teeb, kuidas just see seda teeb ja miks see ĂŒldse seda teeb. Kasutades seda, on ĂŒsna lihtne alustada juhiste arvestamist ja vĂ€lja selgitada, kuhu tĂ€itmisaeg voolab. Kui sul ei ole vastavat ettevalmistust, siis otsid nagu musta kassi pimedas toas. Ma nĂ€en pidevalt inimesi, kes optimeerivad jĂ”udlust, kuid kellel pole vĂ€himatki aimu, mida nad ĂŒldse teevad. Nad vaevlevad vĂ€ga ja ei liigu eriti edasi. Ja kui ma vĂ”tan sama koodi ja lisan sinna paar vĂ€ikest nippi ning saavutan viis- vĂ”i kĂŒmnekordse kiiruskasvu, siis nad ĂŒtlevad: noh, see pole aus, me teadsime ju, et sa oled parem. Üllatav. Millest ma rÀÀkisin... maksumudelist – see on seotud sellega, mis koodi sa kirjutad ja kui kiiresti see keskmiselt toimib ĂŒldises pildis.

Andrei: Ja kuidas sellist mahukust peas hoida? Kas see saavutatakse suure koguse kogemusega, vÔi? Kus sellist kogemust saadakse?

Cliff: Noh, sain kogemus on tulnud keerulisel teel. Programmeerisin assembleris juba siis, kui iga ĂŒksiku kĂ€su mĂ”istmine oli veel vĂ”imalik. See kĂ”lab tobedalt, kuid sellest ajast on mul peas, mĂ€lus igaveseks jÀÀnud Z80 kĂ€skude kogum. Ma ei mĂ€leta inimeste nimesid isegi kohe pĂ€rast vestlust, kuid mĂ€letan koodi, mis kirjutatud 40 aastat tagasi. Naljakas, see meenutab «"teadlase idioodi"».

Madala taseme optimeerimise Ôpetamine

Andrei: Kas on olemas lihtsam viis alustada?

Cliff: Jah ja ei. Riistvara, mida me kĂ”ik kasutame, pole selle aja jooksul palju muutunud. KĂ”ik kasutavad x86, vĂ€lja arvatud ARM-il pĂ”hinevad nutitelefonid. Kui sa ei tegele mingi tĂ”sise sisseehitatud mÔÔtmisega, siis on sul kĂ”ik sama. Olgu, edasi. Ka juhised pole sajandeid muutunud. On vaja minna ja kirjutada midagi Assembleris. Natuke, aga piisavalt, et hakata aru saama. Te naeratate, aga ma rÀÀgin tĂ€iesti tĂ”siselt. On oluline mĂ”ista keele ja riistvara seost. PĂ€rast seda tuleb minna, kirjutada natuke ja teha vĂ€ike mĂ€nguline kompilaator vĂ€ikese mĂ€ngulise keele jaoks. „MĂ€nguline“ tĂ€hendab, et tuleb seda teha arvestatavas ajavahemikus. See vĂ”ib olla superlihtne, kuid peab genereerima juhiseid. Juhiste genereerimise akt aitab mĂ”ista kulumudelit silla ehitamiseks kĂ”rgema taseme koodi ja masina koodi vahel, mida riistvara tĂ€idab. See seos jÀÀb mĂ€llu kompilaatori kirjutamise kĂ€igus. Isegi kĂ”ige lihtsam kompilaator. PĂ€rast seda saab hakata vaatama Java't ja seda, kui sĂŒgavale on seal semantilised lĂ”hed, ning ehitama nende peale keerukamaid sildu. Java's on palju keerulisem mĂ”ista, kas meie sild on hea vĂ”i halb, mis pĂ”hjustab selle kokkuvarisemise ja mis mitte. Aga sul on vaja mingit lĂ€htepunkti, kui vaatad koodi ja mĂ”istad: „aha, see getter peaks iga kord inline'ima.” Ja siis selgub, et mĂ”nikord juhtubki nii, vĂ€lja arvatud olukordades, kus meetod muutub liiga suureks, ja JIT hakkab inline'ima kĂ”ike juhuslikult. Selliste kohtade sooritusvĂ”imet on vĂ”imalik hetkega ennustada. Reeglina töötavad getterid hĂ€sti, kuid seejĂ€rel vaatad suuri kuumi sildu ja mĂ”istad, et seal on mingid funktsiooni kutsed, millel pole selget eesmĂ€rki. Just selles seisneb probleem getterite laialdasel kasutamisel; pĂ”hjus, miks nad ei inline'ita - ei ole selge, kas see on getter. Kui sul on supervĂ€ike koodibaas, saad selle lihtsalt meelde jĂ€tta ja siis öelda: siin on getter, ja seal on setter. Suures koodibaasis elas iga funktsioon omaenda ajalugu, mis pole kellelegi teada. Profilera ĂŒtleb, et oleme kaotanud 24% aega mingis tsĂŒklis ja et selle tsĂŒkli toimimiseks tuleb vaadata iga funktsiooni sees. Seda on raske mĂ”ista, kui sa ei uuri funktsiooni, ja see aeglustab tĂ”siselt arusaamise protsessi. SeetĂ”ttu ma ei kasuta getterite ja setterite pidevat kasutust; olen lĂ€inud uuele tasemele!
Kust leida hinnamudelit? Jah, muidugi, vĂ”ib lugeda midagi... Kuid ma arvan, et parim viis on tegutseda. Luua vĂ€ike kompilaator ja see on parim viis hinnamudeli mĂ”istmiseks ja selle enda mĂ”tetes paigutamiseks. VĂ€ike kompilaator, mis sobiks mikrolaineahju programmeerimiseks — see on algaja ĂŒlesanne. Ma mĂ”tlen, et kui sul on juba programmeerimisoskused, siis peaks neist piisama. KĂ”ik need asjad, nagu stringi parsimine, mis on mingi algebraline vĂ€ljend, tĂ”mmata sealt vĂ€lja Ă”iged matemaatilised toimingud Ă”iges jĂ€rjekorras, vĂ”tta Ă”iged vÀÀrtused registritest — see kĂ”ik on hĂ”lbus. Ja kui sa seda teed, jÀÀb see su ajusse. Ma arvan, et kĂ”ik teavad, mida kompilaator teeb. Ja see annab mĂ”istmise hinnamudelist.

Praktilised nÀited jÔudluse parandamisest

Andrei: Millele veel tasub tÀhelepanu pöörata jÔudluse parandamisel?

Cliff: Andmestruktuurid. Jah, tĂ”epoolest, ma ei ole neid loenguid juba pikka aega pidanud... Rocket School. See, see, on one of the larger and more interesting sessions, "Where Your Performance Goes," I gave students an example: two and a half gigabytes of fintech data were read from a CSV file, and then we had to count the number of products sold. Standard tick market data. UDP packets turned into text format since the 70s. Chicago Mercantile Exchange — things like oil, corn, soybeans, and the like. We needed to count these products, the number of transactions, the average volume of funds and goods, etc. It's pretty straightforward trading math: find the product code (that's 1-2 characters in a hash table), get the sum, add it to one of the transaction sets, add volume, add cost, and a few other items. Very simple math. The toy implementation was very straightforward: everything is in the file, I read the file and move through it, splitting individual records into Java strings, looking for the necessary items in them and summing according to the math described above. And it works at some moderate speed.

Nii lĂ€henemisega on kĂ”ik selge, mis toimub, ja paralleelsed arvutused siin ei aita, eks? Selgub, et viiekordset jĂ”udluse suurendamist saab saavutada lihtsalt Ă”igete andmestructuuride valimisega. See ĂŒllatab isegi kogenud programmeerijaid! Minu konkreetses olukorras oli fookus selles, et ei tohiks teha mĂ€lu eraldamisi kuumas tsĂŒklis. No, see ei ole kogu tĂ”de, aga ĂŒldiselt – ei tohiks eraldada 'kord X', kui X on piisavalt suur. Kui X on kaks ja pool gigabaiti, ei tohiks eraldada midagi 'kord tĂ€he', 'kord rea', vĂ”i 'kord vĂ€lja', midagi sellist. Just sellele kulubki aega. Kuidas see ĂŒldse töötab? Kujutage ette, et teen kĂ”ne String.split() vĂ”i BufferedReader.readLine(). Readline muundab vĂ”rgu kaudu saadud baitidest iga rea jaoks ĂŒhe striingi, iga sada miljonit rida. Ma vĂ”tan selle striingi, analĂŒĂŒsin selle ja viskan minema. Miks viskan? Noh, olen ju selle juba töötlenud, kĂ”ik. Nii et iga bait, mis on loetud nendest 2.7G-st, salvestatakse kaheks sĂŒmboliks striingis, seega juba 5.4G, ja nad ei ole mulle enam millekski vajalikud, seega visatakse nad minema. Kui vaadata mĂ€luliiklust, laeme 2.7G, mis liigub lĂ€bi mĂ€lu ja mĂ€lubussi protsessoris, ja veel kaks korda rohkem saadetakse striingi, mis asub mĂ€lus, ja see kĂ”ik töötatakse ĂŒmber igal uue striingi loomisel. Kuid ma pean selle lugema, riistvara loeb selle, isegi kui see kĂ”ik hiljem ĂŒmber töötatakse. Ja ma pean selle salvestama, sest olen loonud striingi ja vahemĂ€ed on ĂŒlekoormatud – vahemĂ€e maht ei suuda 2.7G mahutada. KokkuvĂ”tteks, iga loetud baidi kohta loen veel kaks lisabaidi ja kirjutan kaks lisabaidi, ning kokku saavad nad suhe 4:1 – sellises sooritusvĂ”imes raiskame mĂ€lu lĂ€bilaskevĂ”imet. Ja edasi selgub, et kui ma teen String.split() – ma ei tee seda kaugeltki esmakordselt; seal sees vĂ”ivad olla veel 6-7 valikut. SeepĂ€rast toob klassikaline CSV lugemiskood koos jĂ€rgneva ridade parsimisega kaasa mĂ€lu ribalaiuse kadu umbes 14:1 vĂ”rreldes sellega, mida te tegelikult oma soovitud nĂ€ete. Kui need vĂ€ljastamised kĂ”rvale jĂ€tta, on vĂ”imalik saavutada viiekordne kiirus.

Ja see ei ole ĂŒldse nii keeruline. Kui vaatate koodi Ă”igest vaatenurgast, muutub kĂ”ik ĂŒsna lihtsaks, kohe kui olete probleemi olemuse mĂ”istnud. Ei tohiks ĂŒldse lĂ”petada mĂ€lu eraldamist: probleem seisneb lihtsalt selles, et teete midagi, mis kohe sureb, ja samal ajal pĂ”letate olulist ressurssi, milleks on sel juhul mĂ€lu ribalaius. See kĂ”ik viib jĂ”udluse langemiseni. x86 puhul tuleb tavaliselt aktiivselt pĂ”letada protsessori takte, aga siin olete kogu mĂ€lu pĂ”letanud varem. Lahendus on vĂ€hendada eraldamiste arvu. 
Teine probleem on see, et kui profiilerit kĂ€ivitada, kui mĂ€lu lint on lĂ”ppenud, just siis, kui see juhtub, siis sa tavaliselt ootad vahemĂ€lu tagastumist, kuna see on tĂ€is prĂŒgi, mida sa just tootnud oled, nende ridadega. SeetĂ”ttu iga laadimis- vĂ”i salvestusoperatsioon muutub aeglaseks, kuna need toovad kaasa vahemĂ€lu möödalaskmised – kogu vahemĂ€lu on aeglane, oodates, millal prĂŒgi vĂ€lja veetakse. SeetĂ”ttu nĂ€itab profiiler lihtsalt sooja juhuslikku mĂŒra, hajutatuna kogu tsĂŒkli ulatuses – ei ole ĂŒhtegi eraldi kuuma instruktsiooni vĂ”i koodi kohta. Ainult mĂŒra. Ja kui vaatad GC tsĂŒkleid, on need kĂ”ik Young Generation'i ulatuses ja ĂŒlimugavad – mikrosekundid vĂ”i millisekundid maksimaalselt. Sest kogu see mĂ€lu sureb koheselt. Sa eraldad miljardeid gigabaite, ja ta lĂ”ikab neid, ja lĂ”ikab, ja jĂ€lle lĂ”ikab. KĂ”ik see toimub vĂ€ga kiiresti. Nii et on odavad GC tsĂŒklid, soe mĂŒra kogu tsĂŒkli ulatuses, kuid me tahame saada 5-kordset kiiruskasvu. Just sel hetkel peaks peas midagi klikkima ja kĂ”lama: 'miks nii?!'. MĂ€lu lint ĂŒlevoolu ei kuvata klassikalises siluri, tuleb kĂ€ivitada riistvaraliste jĂ”udluse loendurite silur ja nĂ€ha seda ise ja otse. Otse mitte, seda vĂ”ib kahtluse alla seada nende kolme sĂŒmptomi kaudu. Kolmas sĂŒmptom on see, kui vaatad, mida sa eraldad, kĂŒsid profiilerilt ja ta vastab: 'Sa tegid miljardi rida, kuid GC töötas tasuta.' Kui see juhtub, mĂ”istad, et oled tootnud liiga palju objekte ja pĂ”letanud kogu mĂ€lu lint. On viis seda probleemi lahendada, kuid see ei ole ilmselge. 

Andmete struktuuriga on probleem: paljas struktuur, mis seisab kĂ”ikide sĂŒndmuste taga, on liiga suur, see on 2.7G kettale, seega on selle koopia tegemine vĂ€ga ebasoovitav – soov oleks laadida see kohe vĂ”rgubuffrist registritesse, et mitte lugeda-kirjutada sinna ja tagasi viis korda. Kahjuks ei paku Java vaikimisi sulle sellist teeki JDK-s. Aga see on ju triviaalne, eks? Sisuliselt on see 5-10 koodi rida, mis lĂ€heb kasutusele sinu enda vahelduva laadija ridade jaoks, mis kordab stringi klassi kĂ€itumist, olles samas ĂŒmberpakendatud alloleva baitide puhvri ĂŒmber. Tulemuseks on, et töötad peaaegu nagu stringidega, aga tegelikult liiguvad seal puhvri suunajad, ja toored bait ei kopeerita kuhugi, ning niimoodi taaskasutatakse samu puhvereid ikka ja jĂ€lle, ning operatsioonisĂŒsteem on Ă”nnelik, et saab vĂ”tta enda kanda asjad, milleks ta on mĂ”eldud, nagu nĂ€iteks peidetud topeltpuhverdamine nende bity puhvritega, ja sina enam ei jahvatata lĂ”putut voolu tarbetutest andmetest. Muide, kas te mĂ”istate, et GC töötamise ajal tagatakse, et iga mĂ€lu eraldamine ei ole pĂ€rast viimast GC tsĂŒklit protsessorile nĂ€htav? Seega ei saa see kĂ”ik kuidagi olla vahemĂ€lu, ja see viib 100%-iliselt tagatud möödaminnani. Suunajaga töötamisel x86-l kestab registreerimise lugemine mĂ€lust 1-2 tsĂŒklit, ja kui see juhtub, siis maksad, maksad, maksad, kuna kogu mĂ€lu on ÜHEKS keskkonnas – ja see ongi mĂ€lu eraldamise maksumus. Tegelik maksumus.

TeisisĂ”nu, andmestruktuurid on need, mida on kĂ”ige raskem muuta. Ja kui sa saad aru, et oled valinud vale andmestruktuuri, mis tulevikus hĂ€vitab jĂ”udluse, on tavaliselt vajalik teha mĂ€rkimisvÀÀrne töö, kuid kui seda ei tehta, lĂ€heb asi hullemaks. Esiteks tuleb mĂ”elda andmestruktuuridele, see on oluline. Peamine kulutus tekib seal, kus kasutatakse mahukaid andmestruktuure stiilis 'ma kopeerisin andmestruktuuri X andmestruktuuri Y, sest Y meeldib mulle rohkem vĂ€limuselt'. Kuid kopeerimise operatsioon (mis tundub odav) tarbib tegelikult mĂ€lu, ja siin peitub kogu kaotatud tĂ€itmisaja probleem. Kui mul on hiiglaslik JSON-string ja ma tahan selle teisendada struktureeritud DOM-puu POJO-ks vĂ”i millegi sarnaseks, siis selle stringi parsimise ja POJO ehitamise operatsioon ning edasi uute pĂ€ringute tegemine POJO-le tĂ€hendab tĂ€iendavaid kulusid – see pole odav. Erandiks on see, kui sa jooksed POJO-de ĂŒle kordades sagedamini kui stringi. Öeldes lihtsalt, vĂ”iks proovida stringi dekodeerida ja vĂ€lja tĂ”mmata ainult vajaliku, ilma et see muutuks mingiks POJO-ks. Kui kĂ”ik see toimub tee peal, kus on nĂ”utav maksimaalne jĂ”udlus, siis igasugused POJO-d on vĂ€listatud – tuleb kuidagi otse stringiga tegeleda.

Miks luua oma programmeerimiskeel

Andrei: Te ĂŒtlesite, et teadlikkuse mudeli loomiseks tuleb kirjutada oma vĂ€ike keel


Cliff: Mitte keel, vaid kompilaator. Keel ja kompilaator on erinevad asjad. Peamine erinevus on peas. 

Andrei: Muide, kui ma ei eksi, katsetate te oma keelte loomisega. Miks?

Cliff: Sest ma saan! Olen poolpensionil, seega on see minu hobi. Olen kogu elu töötanud kellegi teise keelte rakendamise nimel. Samuti olen palju vaeva nĂ€inud koodimise stiiliga. Ja veel muidugi, kuna nĂ€en probleeme teistes keeltes. NĂ€en, et on paremaid viise tuttavate asjade tegemiseks. Ja ma kasutaksin neid. Mind hĂ€irib tĂ”esti nĂ€ha probleeme enda, Java, Python ja igas teises keeles. Praegu kirjutan React Native'is, JavaScriptis ja Elm'is, mis on hobi, mis ei ole pensioni, vaid aktiivse tööga seotud. Ja ma kirjutan ka Pythonis ning tĂ”enĂ€oliselt jĂ€tkan masinĂ”ppe arendamist Java back-end'ide jaoks. Populaarseid keeli on palju ja igal neist on huvitavad omadused. IgaĂŒhel on oma tugevused ja saate proovida kĂ”ik need trikid kokku viia. Seega uurin huvitavaid asju, keele kĂ€itumist, pĂŒĂŒan vĂ€lja mĂ”elda mĂ”istliku semantika. Ja seni suudan! Praegu vĂ”itlen mĂ€lu semantikaga, sest soovin, et see oleks nagu C-s ja Java-s, ning saada tugev mĂ€lumudel ja mĂ€lu semantika laadimise ja salvestamise jaoks. Samuti soovin automaatset tĂŒĂŒbi jĂ€reldust nagu Haskell'is. Nii et pĂŒĂŒan segada Haskell'i sarnast tĂŒĂŒbi jĂ€reldust mĂ€lu funktsioonidega nagu C-s ja Java-s. Sellega olen viimased 2-3 kuud tegelenud, nĂ€iteks.

Andrei: Kui te loote keelt, mis vÔtab parimaid aspekte teistest keeltest, kas olete mÔelnud, et keegi vÔiks teha vastupidist: vÔtta teie ideid ja kasutada neid enda heaks?

Cliff: TĂ€pselt nii sĂŒnnivad uued keeled! Miks on Java sarnane C-ga? Sest C-l oli hea sĂŒntaks, mida kĂ”ik mĂ”istsid, ja Java sai inspiratsiooni sellest sĂŒntaksist, lisades tĂŒĂŒbiohutuse, massiivide piirikontrollid, GC, ja nad parandasid ka mĂ”ningaid asju C-s. Nad lisasid omalt poolt. Kuid nad said tĂ”eliselt tugevalt inspiratsiooni, eks? KĂ”ik seisavad hiiglaste Ă”lgadel, kes olid enne sind – just nii toimub progress.

Andrei: Nii nagu mina aru saan, on teie keel mÀlu kasutamise osas ohutu. Kas olete mÔelnud midagi sarnast Rusti borrow checker'ile rakendada? Kas olete seda vaadanud, kuidas see teile meeldib?

Cliff: Noh, ma olen C keeles juba igavesti kirjutanud, kĂ”ikide nende malloc ja free abil, ning haldan kĂ€sitsi eluea pikkust. Teate, 90-95% kĂ€sitsi hallatavatest eluaegadest on sama struktuuriga. Ja see on vĂ€ga, vĂ€ga valus omasoodu sellega tegeleda. Tahaks, et kompilaator lihtsalt ĂŒtleks, mis seal toimub ja mida sa oma tegevustega saavutasid. MĂ”nede asjade puhul teeb borrow checker seda automaatselt. Ja ta peab automaatselt andmeid vĂ€lja kirjutama, kĂ”ike mĂ”istma ja isegi mitte koormama mind sellega, et seda mĂ”istmist vĂ€lja tuua. Ta peaks vĂ€hemalt tegema kohalikku eskape-analĂŒĂŒsi, ja ainult siis, kui tal ei lĂ€he korda, peaks juurde lisama tĂŒĂŒbi annotatsioone, mis kirjeldavad eluaega – ja sarnane skeem on oluliselt keerulisem kui borrow checker vĂ”i ĂŒldse mingi olemasolev mĂ€lu kontrollija. Valik „kĂ”ik on korras” ja „ma ei saanud aru” — ei, see peab olema midagi paremat. 
Seega, kui rÀÀkida inimesest, kes on kirjutanud palju C-koodi, siis arvan, et automaatse elutsĂŒkli haldamise tugi on ÀÀrmiselt oluline. Samuti hĂ€irib mind, kui palju mĂ€lu Java kasutab, ja peamine kaebus on GC. Java mĂ€lu eraldamisel ei saa sa tagasi mĂ€lu, mis oli kohalik viimases GC tsĂŒklis. Keeltes, kus mĂ€lu juhtimine on tĂ€psem, ei ole see nii. Kui kutsub ĂŒles malloc'i, saad kohe mĂ€lu, mida just kasutati. TĂŒĂŒpiliselt teed mĂ€luga mingid ajutised asjad ja saadad selle kohe tagasi. Ja see tagastatakse kohe malloc'i puumi, kust jĂ€rgmine malloc tsĂŒkkel toob selle jĂ€lle vĂ€lja. Seega vĂ€hendatakse tegelikku mĂ€lu kasutust elavate objektide kogumini antud hetkel, pluss lekete kogum. Ja kui sul ei leki absoluutselt viisil, mis oleks ebaviisakas, asub enamik mĂ€lu vahemĂ€lus ja protsessoris, ja see töötab kiiresti. Kuid see nĂ”uab palju kĂ€sitsi mĂ€lu juhtimist malloc ja free abil, kutsudes neid Ă”igel ajal ja Ă”iges kohas. Rust suudab sellega Ă”igesti toime tulla ja paljudel juhtudel isegi pakkuda suuremat jĂ”udlust, kuna mĂ€lu tarbimine kitseneb ainult praegustele arvutustele – vastupidiselt ootamisele jĂ€rgmise GC tsĂŒkli ajal, mis mĂ€lu vabastab. LĂ”puks saime vĂ€ga huvitava viisi, kuidas jĂ”udlust parandada. Ja see on ĂŒsna vĂ”imas – ma tegin selliseid asju andmete töötlemisel fintechis ja see vĂ”imaldas saavutada umbes viis korda kiiremat tulemust. See on ĂŒsna suur kiirus, eriti maailmas, kus protsessorid ei muutu kiiremateks ja me kĂ”ik ootame endiselt tĂ€iustusi.

Performantsiinseneri karjÀÀr

Andrei: Samuti sooviksin rÀÀkida karjÀÀrist laiemalt. Te olete tuntuks saanud oma töö tĂ”ttu JIT-is HotSpotis ja hiljem liikusite Azulisse – mis on samuti JVM ettevĂ”te. Kuid seal tegelesite rohkem riistavaraga kui tarkvaraga. Ja siis Ă€kki suundusite Big Data ja masinĂ”ppe poole, seejĂ€rel pettuste avastamise peale. Kuidas see juhtus? Need arendusvaldkonnad on vĂ€ga erinevad.

Cliff: Olen juba ĂŒsna pikka aega programmeerimistehnika parjutanud ja kogenud erinevates ĂŒlesannetes. Ja kui inimesed ĂŒtlevad: „oh, sina oled see, kes tegi JIT-i Java jaoks!“, on see alati naljakas. Kuid enne seda tegelesin PostScripti klooni loomisega – selle keelega, mida Apple kunagi oma laserprinterites kasutas. Enne seda tegin Forth-i keele rakendust. Arvan, et minu jaoks on ĂŒldine teema tööriistade arendamine. Kogu elu olen teinud tööriistu, mille abil teised inimesed kirjutavad oma Ă€gedaid programme. Kuid olen tegelenud ka operatsioonisĂŒsteemide, draiverite, tuumadebĂŒĂŒgide, operatsioonisĂŒsteemide arendamiseks mĂ”eldud keelte arendamisega, mis alustasid triviaalsetest, kuid ajaga muutusid jĂ€rjest keerulisemaks. Kuid pĂ”hiteema on ikkagi tööriistade arendamine. Suur osa elust kulus Azul ja Sun vahel ja see kĂ€sitles Java't. Kuid kui sukeldusin Suurandmete ja MasinĂ”ppe valdkonda, panin taas selga oma piduliku mĂŒtsi ja rÀÀkisin: „Oh, nĂŒĂŒd on meil tekkinud keeruline probleem ja siin toimub tegelikult hunnik huvitavaid asju ja inimesi, kes midagi teevad“. See on suurepĂ€rane arengutee, mida tasub lĂ€bida.

Jah, ma armastan hajusaid arvutusi. Minu esimene töö oli ĂŒlikooli ajal, C keeles, reklaamiprojektiga. Need olid hajusaid arvutusi Zilog Z80 kiipidel, mis kogusid andmeid analoogsete optiliste tekstide Ă€ratundmise jaoks, mida tegi tegelik analooganalĂŒsaator. See oli Ă€ge ja tĂ€iesti ebatavaline teema. Kuid seal olid probleemid, mingi osa ei olnud Ă”igesti Ă€ratuntud, seega oli vajalik pilti vĂ€lja vĂ”tta ja nĂ€idata seda inimesele, kes oli juba silmadega lugenud, ja edastada, mida seal öeldakse; ja seetĂ”ttu olid seal andmetööd, ja nendel andmetööd olid oma keel. Oli backend, mis töötles seda kĂ”ike – paralleelselt töötavad Z80, kus igaĂŒhel olid avatud vt100 terminalid – ĂŒks inimese kohta, ja Z80-l oli olemas paralleelprogrammeerimise mudel. Üks ĂŒhine mĂ€lutĂŒkk, mida jagasid kĂ”ik Z80 selle tĂ€hekujulise konfiguratsiooni sees; jagati nii tagaplaat kui ka pool RAM-i jagati vĂ”rgu sees, ja veel pool oli privaatne vĂ”i lĂ€ks millelegi muule. MĂ”istlikult keeruline paralleelne hajus sĂŒsteem jagatud... pool-jagatava mĂ€luga. Millal see siis oli... Ei oska enam meenutada, kuskil 80ndate keskpaiku. Üsna ammu. 
Jah, oletame, et 30 aastat on piisavalt pikk aeg. Jagatud arvutustega seotud ĂŒlesanded on eksisteerinud juba pikka aega, inimesed on ammu nendega vĂ”idelnud. Beowulf-klastritega. Sellised klastrid nĂ€evad vĂ€lja nagu... NĂ€iteks: sul on Ethernet ja su kiire x86 on ĂŒhendatud sellele Ethernetile, ja nĂŒĂŒd tahad sa saada vale jagatud mĂ€lu, sest toona ei saanud keegi tegeleda jagatud arvutuste kodeerimisega, see oli liiga keeruline ja seetĂ”ttu oli vale jagatud mĂ€lu koos x86 mĂ€lu lehekĂŒlgede kaitsega. Ja kui sa kirjutasid sellesse lehekĂŒlge, siis me ĂŒtlesime teistele protsessoritele, et kui nad pÀÀsevad juurde sellele samale jagatud mĂ€lule, tuleb see selt sinult laadida. Nii tekkis midagi, mis meenutas vahemĂ€lu koherentsuse toetamise protokolli ja tarkvara selle jaoks. Huvitav kontseptsioon. Tegelik probleem oli muidugi midagi muud. KĂ”ik see toimis, kuid sa said kiiresti tootlikkuse probleemide osaliseks, sest keegi ei mĂ”istnud tootlikkuse mudelit piisavalt hĂ€sti – millised olid mĂ€lule pÀÀsu mustrid, kuidas vĂ€ltida, et node'id pidevalt ĂŒksteist ei pingsaks, ja nii edasi.

H2O-s ma mĂ”tlesin jĂ€rgmist: arendajad vastutavad selle eest, et mÀÀrata, kus peitub paralleelsus ja kus seda ei ole. Olen loonud sellise kodeerimise mudeli, et kĂ”rgetasemelise koodi kirjutamine on lihtne ja mugav. Kuid aeglaselt töötava koodi kirjutamine on keeruline ning see nĂ€eb halb vĂ€lja. Aeglase koodi kirjutamiseks tuleb tĂ”siselt pingutada, tuleb kasutada mittestandardsed meetodeid. Aeglane kood on esmapilgul silmatorkav. SeetĂ”ttu kirjutatakse tavaliselt kood, mis töötab kiiresti, kuid tuleb mĂ”ista, mida teha jagatud mĂ€lu korral. KĂ”ik see on seotud suurte massiividega ja seal kĂ€itumine sarnaneb mittevolatiilsete suurte massiividega paralleelses Javas. Kujutage ette, et kaks lĂ”ime kirjutavad paralleelsesse massiivi, ĂŒks neist vĂ”idab ja teine loomulikult kaotab, ja te ei tea, kes neist on kes. Kui nad ei ole volatiilsed, siis vĂ”ib jĂ€rjekord olla suvaline – ja see töötab tĂ”eliselt hĂ€sti. Inimesed tĂ”eliselt hoolivad operatsioonide jĂ€rjekorrast, nad paigutavad Ă”igesti volatile ja Ă”igetes kohtades ootavad nad probleemidega seonduvat jĂ”udluses, mis on seotud mĂ€luga. Vastupidisel juhul kirjutaksid nad lihtsalt koodi tsĂŒklitena alates 1 kuni N, kus N on mĂ”ned triljonid, lootes, et kĂ”ik keerulised juhtumid muutuvad automaatselt paralleelseks – ja seal see ei toimi. Kuid H2O ei ole see ei Java ega Scala, seda vĂ”ib pidada „Java miinus miinus”, kui soovite. See on vĂ€ga arusaadav programmis stiil ja sarnaneb lihtsa koodi kirjutamisega C vĂ”i Java keeles tsĂŒklite ja massiividega. Samas vĂ”ib mĂ€lu töödelda terabaitide kaupa. Kasutan H2O-d ikka veel. Aeg-ajalt kasutan seda erinevates projektides – ja see on endiselt kĂ”ige kiireim lahendus, kĂŒmneid kordi konkurentidest ees. Kui teete Big Data-d veergandmetega, on H2O-d vĂ€ga raske ĂŒletada.

Tehnilised vÀljakutsed

Andrei: Milline on olnud teie karjÀÀri jooksul kÔige suurem vÀljakutse?

Cliff: Kas arutame tehnilist vĂ”i mitte-tehnilist osa? Ütleksin, et kĂ”ige suuremad vĂ€ljakutsed on mitte-tehnilised. 
Mis osas on tehnilised vĂ€ljakutsed. Ma lihtsalt vĂ”itsin nad. Ma isegi ei tea, mis neist kĂ”ige suurem oli, aga neid oli mitu ĂŒsna huvitavat, millele kulus palju aega ja vaimset pingutust. Kui ma lĂ€ksin Suni, olin kindel, et suudan teha kiire kompilaatori, kuid hulk vanemaid arendajaid ĂŒtlesid, et mul ei Ă”nnestu kunagi. Ent ma lĂ€ksin selle teedpidi, kirjutasin kompilaatori kuni registrite jaotajani ning see oli pĂ€ris kiire. Ta oli sama kiire kui kaasaegne C1, kuid toona oli jaotaja palju aeglasem ja tagantjĂ€rele vaadates - see oli suurte andmestruktuuride probleem. Mul oli neid vaja, et kirjutada graafiline registrite jaotaja ning ma ei mĂ”istnud dilemmat, mis tekkis koodi vĂ€ljendatavuse ja kiirusena, mis eksisteeris sellel ajal ja oli vĂ€ga oluline. Selgus, et andmestruktuur ĂŒletas tavaliselt x86 arhiitekti kande suuruse ja seega, kui ma algselt eeldasin, et registrite jaotaja kulutab 5-10 protsenti kogu JVM-i ajast, siis tegelikult kujunes see 50 protsendi peale.

Aeg möödus, kompilaator muutus jĂ€rjest tĂ€psemaks ja tĂ”husamaks, lĂ”petas ĂŒha enam halbade koodide genereerimise ning jĂ”udlus hakkas jĂ€rjest rohkem meenutama C kompilaatori vĂ€ljundit. Kui sa loomulikult ei kirjuta mingit jama, mida isegi C ei suuda kiirendada. Kui kirjutad koodi nagu C-s, siis saad ka C tasemel jĂ”udluse palju sagedamini. Ja mida edasi, seda rohkem saadi kood, mis asĂŒmptootiliselt sarnanes C tasemega, registrite allocator hakkas meenutama midagi tĂ€iustatud
 sĂ”ltumata sellest, kas su kood töötas kiiresti vĂ”i aeglaselt. JĂ€tkasin registrite allocatori tĂ€iustamist, et see teeks paremaid eraldamisi. See muutus aeglasemaks ja aeglasemaks, aga andis jĂ€rjest paremat jĂ”udlust olukordades, kus kedagi teist enam ei aidanud. Ma sain sukelduda registrite allocatorisse, kaevata sinna kuu aega tööd ja ĂŒhtĂ€kki hakkas kogu kood töötama 5% kiiremini. See juhtus korduvalt ja registrite allocatorist sai midagi kunstiteose sarnast – kĂ”ik armastasid vĂ”i vihkasid seda, ja akadeemia inimesed kĂŒsisid kĂŒsimusi, nagu 'miks kĂ”ik just nii toimub', miks mitte lineaarne skaneerimine, ja milles on vahe. Vastus on endiselt sama: graafivĂ€rvimise pĂ”hine allocator pluss vĂ€ga hoolikas vahetuskoodiga töötamine on vĂ”idurelv, parim kombinatsioon, mida keegi ei suuda vĂ”ita. Ja see on tegelikult ĂŒsna ebaselge asi. KĂ”ik muu, mida seal kompilaator teeb – need on ĂŒsna tuntud asjad, kuigi need on ka kunstitasemele viidud. Ma olen alati teinud asju, mis peaksid kompilaatori kunstiteoseks muutma. Kuid midagi neist ei olnud midagi erakordset – vĂ€lja arvatud registerallocator. Fokus on selles, et tuleb hoolikalt ĂŒhendada koormuse all ja kui see juhtub (ma saan selgitada pĂ”hjalikumalt, kui see huvitab), tĂ€hendab see, et saab inline'ida agressiivsemalt, ilma et oleks ohtu ĂŒletada jĂ”udluse graafiku murdumist. Sel ajal oli palju tĂ€islahendusega kompilaatoreid, mis olid kaunistatud igasuguste vidinate ja trikkidega, kus olid register allocatorid, kuid keegi ei suutnud enam nii teha.

Probleem on selles, et kui lisad meetodeid, mis on inline'imiseks sobivad, suurendades ja suurendades inline'imise ala, siis kasutatavate vÀÀrtuste hulk ĂŒletab kiiresti registrite arvu ja pead hakkama osasid eemaldama. Kriitiline tase saavutatakse tavaliselt siis, kui allocator loobub, ning ĂŒks hea splittimise kandidaat maksab rohkem kui teine, mistĂ”ttu pead eemaldama tĂ€iesti ootamatuid asju. Inline'imise vÀÀrtus seisneb selles, et kaotad osa overhead'ist, mis tuleneb kutsumisest ja salvestamisest, sa nĂ€ed vÀÀrtusi seestpoolt ja saad neid edasi optimeerida. Inline'imise hind seisneb selles, et tekib suur hulk elavaid vÀÀrtusi, ning kui su registri allocator eemaldab rohkem, kui vajalik, kaotad koheselt. SeepĂ€rast on enamikul allokaatoritest probleem: kui inline'imine ĂŒletab teatud piiri, algavad kĂ”ik asjad, mis kĂ”ik toovad kaasa vĂ€henemise ja tootlikkuse on praktiliselt kadunud. Need, kes teevad kompilaatorit, lisavad teatud tĂ”enĂ€osusi: nĂ€iteks, et peatada inline'imine, alates teatud piisavalt suurest suurusest, kuna kĂ”ik allokatsioonid mĂ”jutavad seda. Nii moodustub graafiku hĂ€ire – sa inline'id, inline'id, tootlikkus kasvab aeglaselt – ja siis pauk! – see kukub jĂ€rsult alla, kuna oled inline'inud liiga palju. Nii see kĂ”ik töötas kuni Java tulekuni. Java nĂ”uab palju rohkem inline'imist, seega pidin tegema oma allokaatori palju agressiivsemaks, et see oleks tasakaalus, mitte kuitenki langenud. Ja kui sa oled liiga palju inline'inud – ta hakkab vĂ€ikeseid eemaldama, kuid siiski tuleb hetk, mil „enam ei ole eemaldamist”. See on huvitav tĂ€helepanek ja see tuli mulle lihtsalt kuskilt, mitte ilmselgelt, kuid tasus end hĂ€sti Ă€ra. Ma alustasin agressiivse inline'imisega ja see viis mind kohtadesse, kus Java ja C tootlikkus kĂ”rvuti. Nad on tĂ”eliselt lĂ€hedased – ma saan kirjutada Java koodi, mis on oluliselt kiirem kui C kood ja vastavalt sellele, kuid keskmiselt, suures asjade pildis, on nad enam-vĂ€hem vĂ”rdsed. Tundub, et osa sellest teenest on registri allocator, mis vĂ”imaldab mul inline'ida maksimaalselt pĂ”himĂ”tteliselt. Ma lihtsalt inline'in kĂ”ik, mida nĂ€en. KĂŒsimus on selles, kas allocator töötab hĂ€sti ja kas tulemuseks on mĂ”istlikult töötav kood. See oli suur vĂ€ljakutse: kĂ”ike seda mĂ”ista ja end tööle panna.

Veidi registri ja multi-tuumade jaotamisest

Vladimir: Registrite eraldamise probleemid nÀivad olevat mingi igavese lÔputu teema. Kas on kunagi juhtunud, et mingi idee tundus paljutÔotav, kuid siis kukkus praktikas lÀbi?

Cliff: Loomulikult! Registererimist edastamine on valdkond, kus pĂŒĂŒad NP-tĂ€ieliku probleemi lahendamiseks leida mingeid heuristilisi meetodeid. Ja sa ei suuda kunagi saavutada ideaalset lahendust, eks? See on lihtsalt vĂ”imatu. Vaadake, Ahead of Time kompileerimine – see töötab samuti halvasti. Jutt kĂ€ib siin keskmistest juhtudest. TĂŒĂŒpilisest jĂ”udlusest, nii et saad minna ja mÔÔta midagi, mida pead heaks tĂŒĂŒpiliseks jĂ”udluseks – lĂ”puks töötad ju selle parandamise nimel! Registererimise edastamine on teema, mis on tĂ€ielikult joonistatud jĂ”udlusele. Kui sul on esimene prototĂŒĂŒp, mis töötab ja vĂ€rvib vajamineva, siis algab töö jĂ”udluse nimel. Pead Ă”ppima, kuidas hĂ€sti mÔÔta. Miks see on oluline? Kui on selged andmed, saad vaadata erinevaid osi ja nĂ€ha: aha, see aitas siin, aga seal kĂ”ik kukkus kokku! Tulevad mĂ”ned head ideed, sa lisad uue heuristika ja Ă€kki kĂ”ik hakkab keskmiselt veidi paremini tööle. VĂ”i ei hakka. Mul on olnud sadu juhtumeid, kus me vĂ”itlesime viie protsendi jĂ”udluse nimel, mis eraldas meie lahendust eelnevatest registererijatest. Ja iga kord nĂ€eb see vĂ€lja nii: kusagil tuli vĂ”it, kusagil kaotus. Kui sul on head jĂ”udlusanalĂŒĂŒsi tööriistad, saad leida kaotavad ideed ja mĂ”ista, miks nad kaotavad. VĂ”ib-olla tasub kĂ”ik jĂ€tta nii, nagu on, vĂ”i vĂ”tad tĂ”sisemalt ette peenhÀÀlestuse, vĂ”i lĂ€hed ja parandad midagi muud. See on terve hulk asju! Ma tegin selle laheda hĂ€ki, aga mul on vaja ka seda, seda ja seda – ja nende kogumine annab teatud parendusi. Üksikud ideed vĂ”ivad kukkuda. Nii see on NP-tĂ€ielike probleemide jĂ”udlusega töötamise loomuses.

Vladimir: Tundub, et asjad nagu allocators'ite vĂ€rvimine on juba lahendatud ĂŒlesanne. Noh, teie jaoks on see lahendatud, arvestades, mida te rÀÀgite, kas siis tasub ĂŒldse


Cliff: See ei ole lahendatud nagu selline. Sina pead selle 'lahendatud' muutma. On keerulisi ĂŒlesandeid ja need tuleb lahendada. Kui see on tehtud, on aeg keskenduda tootlikkusele. Sellele ĂŒlesandele tuleb lĂ€heneda vastavalt – teha mÔÔtmisi, koguda statistikat, selgitada olukordi, kui tagasiviimisega eelmisele versioonile su vana nipp jĂ€lle tööle hakkas (vĂ”i vastupidi, lakkas töötamast). Ja mitte loobuda, kuni millegi saavutad. Nagu ma juba ĂŒtlesin, kui Ă€gedad ideed, mis ei toiminud, siis ideede valdkonnas on registreerimisvahendites umbkaudu lĂ”pmatu. NĂ€iteks vĂ”ib lugeda teaduslikke publitseeringuid. Kuigi tĂ€na on see valdkond liikunud aeglasemalt ja on selgem kui oma nooruses. Sellegipoolest on seal tohutu hulk inimesi tööle ja kĂ”ik nende ideed vÀÀrivad proovimist; kĂ”ik ootavad oma aega. Ja sa ei saa öelda, kui head need on, kui sa neid ei proovi. Kui hĂ€sti need integreeruvad kĂ”igega muuga sinu allokatsioonis, sest allokaator teeb palju erinevaid asju, ja mĂ”ned ideed sinu spetsiifilises allokaatoris ei tööta, aga teises allokaatoris – kergelt. Peamine viis allokaatori vĂ”itmiseks on aeglane jama pĂ”hiteest vĂ€lja tĂ”mmata ja sundida jagama aeglaste teede piiridel. Seega, kui sa tahad GC-d kĂ€ivitada, minna aeglast teed, deoptiimiseerida, vĂ€lja visata erandi, kĂ”ik sellelaadsed asjad – sa tead, et need asjad on suhteliselt haruldased. Ja nad on tĂ”epoolest haruldased, ma kontrollisin. Sa teed lisatööd ja tĂ€nu sellele kaovad paljud piirangud nendel aeglastel teedel, kuid see ei ole vĂ€ga oluline, sest need on aeglased ja nendel harva kĂ€iakse. NĂ€iteks nullviit – see ei juhtu kunagi, eks? Peab olema mitu teed erinevate asjade jaoks, kuid nad ei tohiks peamise teega seguneda. 

Vladimir: Mida arvate palju tuumade kohta, kui tuumi on kohe tuhandeid? Kas see on kasulik asi?

Cliff: GPU edu nÀitab, et see on tÔeliselt kasulik!

Vladimir: Need on ĂŒsna spetsialiseeritud. Aga mis saamoodust on ĂŒldotstarbelised protsessorid?

Cliff: Noh, see oli Azul'i Ă€rimudel. Vastus tuli juba ajal, mil inimesed armastasid vĂ€ga ettearvatavat jĂ”udlust. Sel ajal oli parallelkoodi kirjutamine keerukam. H2O koodimudel skaleerub hĂ€sti, kuid see ei ole ĂŒldotstarbeline mudel. Vaevu, et natuke ĂŒldisem kui GPU kasutamisel. Kas me rÀÀgime sellise asja arendamise keerukusest vĂ”i selle kasutamise keerukusest? NĂ€iteks, huvitav Ă”ppetund, mille Azul mulle Ă”petas, oli see, et vĂ€ikesed vahemĂ€lud on tĂ€iesti normaalsed. 

Elu suurim vÀljakutse

Vladimir: Kuidas on lood mitte tehniliste vÀljakutsetega?

Cliff: Suurim vĂ€ljakutse oli mitte olla... lahke ja hea inimestega. Selle tagajĂ€rjel sattusin pidevalt ÀÀrmiselt konfliktsetesse olukordadesse. Nendes olukordades teadsin, et kĂ”ik lĂ€heb valesti, kuid ma ei teadnud, kuidas edasi liikuda nende probleemide lahendamisel ja ei suudnud nendega toime tulla. Palju pikaajalisi probleeme, mis kestsid kĂŒmneid aastaid, tekkis just niimoodi. See, et Java-s on C1 ja C2 kompilaatorid, on selle otsene tagajĂ€rg. Samuti on see, et Java-s ei olnud kĂŒmme aastat jĂ€rjest mitmeastmelist kompileerimist, samuti otsene tagajĂ€rg. On ilmne, et meil oli selline sĂŒsteem vajalik, kuid mitte ilmne, miks seda ei olnud. Mul olid probleemid ĂŒhe inseneriga... vĂ”i inseneride grupiga. Aegade alguses, kui alustasin tööd Sunis, olin... Okei, mitte ainult siis, mul on tegelikult alati oma arvamus. Ja ma pidasin tĂ”eks, et vĂ”in lihtsalt oma tĂ”de otse vĂ€lja öelda. Eriti kuna ma olin ĆĄokeerivalt Ă”ige suure osa ajast. Ja kui selline lĂ€henemine sulle ei meeldi... eriti kui sa ilmselgelt eksid ja teed jama... Üldiselt suudavad vĂ€hesed inimesed taluda sellist suhtlemisviisi. Kuigi mĂ”ned suudavad, nĂ€iteks mina. Olen kogu oma elu ehitanud meritokraatlikele pĂ”himĂ”tetele. Kui sa nĂ€itad mulle midagi vale, siis pöördun ma kohe ringi ja ĂŒtlen: sa ĂŒtlesid jama. Samuti vabandan ja kĂ”ike muud, tunnustan saavutusi, kui neid ĂŒldse on, ja teen teisi Ă”igeid samme. Teisest kĂŒljest olen ma ĆĄokeerivalt Ă”ige ĆĄokeerivalt suure protsendi kogu ajast. Ja see ei tööta inimeste suhete osas eriti hĂ€sti. Ma ei ĂŒrita olla armas, vaid panen kĂŒsimuse teravaks. 'See ei hakka kunagi tööle, sest ĂŒks, kaks ja kolm.' Ja nemad: 'Oho!'. Oli ka teisi tagajĂ€rgi, mida oleks parem ilmselt vahele jĂ€tta: nĂ€iteks abielu lahutamine ja kĂŒmme aastat kestnud depressioon pĂ€rast seda.

VĂ€ljakutse on vĂ”itlus inimeste ja nende arusaamaga sellest, mida sa saad vĂ”i ei saa teha, mis on oluline ja mis mitte. On olnud palju vĂ€ljakutseid kodeerimisstiili ĂŒle. Ma kirjutan endiselt palju koodi ja tookord pidin isegi aeglustuma, sest tegin liiga palju paralleelseid ĂŒlesandeid ja tegin neid halvasti, selle asemel et keskenduda ĂŒhele. Kahe peale vaadates kirjutasin ma poole Java JIT meeskonna koodist, C2 meeskonnast. JĂ€rgmine kiiruselt kodeerija kirjutas pool aeglasemalt, jĂ€rgmine veel pool aeglasemalt ja see oli eksponentsiaalne langus. Seitsmes inimene selles reas oli vĂ€ga, vĂ€ga aeglane – nii see alati on! Ma puutusin kokku hulga koodiga. Ma vaatasin, kes mida kirjutab, ilma eranditeta, ma kammisin nende koodi, vaatasin kĂ”iki ĂŒle ja jĂ€tkasin ise rohkem koodi kirjutamist, kui ĂŒkski neist. Inimestega selline lĂ€henemine ei toimi hĂ€sti. MĂ”ned ei meeldi sellele. Ja kui nad ei suuda sellega toime tulla, algavad igasugused pretensioonid. NĂ€iteks ĂŒhel pĂ€eval öeldi mulle, et lĂ”petan koodi kirjutamise, sest ma kirjutan liiga palju koodi, ja see seab meeskonna ohtu, ja minu jaoks kĂ”las see kĂ”ik nagu nali: mees, kui kogu ĂŒlejÀÀnud meeskond kaob ja ma jĂ€tkan koodi kirjutamist, kaotad ainult poole meeskonnast. Teiselt poolt, kui ma jĂ€tkan koodi kirjutamist ja sa kaotad poole meeskonnast – see kĂ”lab nagu vĂ€ga halb juhtimine. Ma ei ole kunagi tĂ”eliselt selle ĂŒle mĂ”elnud, ma ei ole kunagi seda maininud, aga see oli ikkagi kuskil mu peas. Teadvuse tagakĂŒljel keerles mĂ”te: „Kas te kĂ”ik naljatate?“. Nii et suurim probleem olin mina ja minu suhted inimestega. NĂŒĂŒd mĂ”istan ennast palju paremini, ma juhtisin pikka aega programmeerijate tiimi, ja nĂŒĂŒd ĂŒtlen inimestele otse: tead, ma olen selline nagu olen, ja teil tuleb sellega toime tulla – ei ole midagi, kui ma siin seisan? Ja kui nad hakkasid sellega toime tulema, hakkas kĂ”ik tööle. Ma ei ole tegelikult halb ega hea, mul ei ole halbu kavatsusi ega egoistlikke pĂŒĂŒdeid, see on lihtsalt minu olemus, ja see on millegagi elama peab.

Andrei: Viimasel ajal on kĂ”ik hakanud rÀÀkima introvertide eneseteadvusest ja ĂŒldiselt pehmetest oskustest. Mida selle kohta öelda?

Cliff: Jah, see oli arusaamine ja Ă”ppetund, mille ma sain abikaasast lahkumisest. Mida ma selle lahutuse kĂ€igus sain, on enese mĂ”istmine. Nii hakkasin ma mĂ”istma ka teisi inimesi. MĂ”istma, kuidas see suhtlemine toimib. See viis avastusteni, mis tulid ĂŒksteise jĂ€rel. Selgus, kes ma olen ja mida endast kujutan. Mida ma teen: kas ma olen ĂŒlesande pĂ€rast mures, vĂ”i vĂ€ldin konflikti, vĂ”i midagi muud – ja selline eneseteadvuse tase aitab tĂ”eliselt end kontrolli all hoida. PĂ€rast seda lĂ€heb kĂ”ik palju lihtsamalt. Üks asi, mille olen avastanud mitte ainult enda, vaid ka teiste programmeerijate puhul, on vĂ”imetus sĂ”nadega mĂ”tteid vĂ€ljendada, kui oled emotsionaalses stressis. NĂ€iteks, istud ja koodid, oled voos, ja siis tulevad inimesed ja hakkavad hĂŒsteeriliselt karjuma, et midagi on katki, ja nĂŒĂŒd rakendatakse sinu suhtes ÀÀrmuslikke meetmeid. Ja sa ei suuda isegi sĂ”na öelda, sest oled emotsionaalses stressis. Saadud teadlikkus aitab valmistuda selleks hetkel, kogeda seda ja liikuda tagasiastumisplaani, pĂ€rast mida saad juba midagi teha. Nii et jah, kui hakkad mĂ”istma, kuidas see kĂ”ik töötab – on see suur, elu muutav sĂŒndmus. 
Ma ei suutnud ise Ă”igesti sĂ”nu leida, kuid mĂ€letan tegevuste jĂ€rjestust. Asjaolu on selles, et see reaktsioon on sama fĂŒĂŒsiline kui verbaalne, ja sul on vaja ruumi. Sellist ruumi, zen'i mĂ”ttes. Just seda tuleb seletada ja seejĂ€rel kohe kĂ”rvale astuda – puhtalt fĂŒĂŒsiliselt. Kui ma sĂ”nades vaiksen, saan olukorda emotsioonide osas töötleda. Kui adrenaliin jĂ”uab ajju, lĂŒlitab see sind 'löök vĂ”i pĂ”gene’ reĆŸiimi, sa ei saa enam midagi öelda, ei – nĂŒĂŒd oled sa idioot, löömiseks mĂ”eldud insener, kes ei suuda vÀÀrikat vastust anda ega isegi rĂŒnnakut peatada, ning rĂŒndaja vĂ”ib vabalt korduvalt rĂŒnnata. Alustuseks pead jĂ€lle iseendaks saama, kontrolli tagasi saama, 'löök vĂ”i pĂ”gene’ reĆŸiimist vĂ€lja astuma.

Ja selleks on vajalik verbaalne ruum. Lihtsalt vabalt ruumi. Kui ĂŒldse midagi öelda, siis vĂ”ib just seda vĂ€ljendada ja seejĂ€rel minna tĂ”eliselt leidma endale "ruumi": minna jalutama parki, sulguda duĆĄi alla – see ei ole oluline. Peamine on ajutiselt olukorrast lahti saada. Kui suudad vĂ€hemalt mĂ”neks sekundiks vĂ€lja lĂŒlituda, tuleb kontroll tagasi, hakkad mĂ”tlema selgemalt. "Hea kĂŒll, ma ei ole mingi idioot, ma ei tee lolluseid, ma olen pĂ€ris kasulik inimene." Kui oled suutnud end veenda, on aeg liikuda jĂ€rgmisele etapile: mĂ”ista, mis juhtus. Sulle rĂŒnnati, rĂŒnnak tuli ootamatult, see oli ebaaus ja madal lĂ”ks. See on halb. JĂ€rgmine samm on mĂ”ista, miks rĂŒndaja seda tegi. TĂ”eliselt, miks? VĂ”ib-olla sellepĂ€rast, et ta on ise vihane? Miks ta on vihane? NĂ€iteks sellepĂ€rast, et ta on ise eksinud ja ei suuda vastutust vĂ”tta? Just niimoodi tuleb olukord ettevaatlikult muuta. Kuid selleks on vajalik manööverdusruum, verbaalne ruum. KĂ”ige esimene samm on katkestada verbaalne kontakt. Lahkuda arutelust sĂ”nades. TĂŒhistada see, minna minema nii kiiresti kui vĂ”imalik. Kui see on telefonikĂ”ne – pane lihtsalt toru Ă€ra – see on oskus, mille olen saanud endise naisest suhtlemisest. Kui vestlus ei vii kuhugi heasse kohta, ĂŒtle lihtsalt "nĂ€gemiseni" ja pane toru Ă€ra. Teiselt poolt toru: "bla-bla-bla", sa vastad: "aah, keda huvitab!" ja paned toru Ă€ra. Lihtsalt katkestad vestluse. Viie minuti pĂ€rast, kui su vĂ”ime ratsionaalselt mĂ”elda tagasi tuleb, ja sa natuke jahtud, on vĂ”imalik mĂ”elda, mis ĂŒldse juhtus ja mis edasi toimub. Ja alustada mĂ”testatud vastuse koostamist, mitte lihtsalt reageerida emotsioonidele. Minu jaoks oli iseteadvuses lĂ€bimurre just see, et emotsionaalses stressis ma ei saa rÀÀkida. VĂ€lja minna sellest seisundist, mĂ”elda ja planeerida, kuidas vastata ja probleeme kompenseerida – need on Ă”iged sammud olukordades, kus sa ei saa rÀÀkida. KĂ”ige lihtsam viis on pĂ”geneda olukorrast, kus emotsionaalne stress avaldub, ja lihtsalt lĂ”petada selles stressis osalemine. PĂ€rast seda saad tagasi mĂ”tlema hakata, kui su mĂ”te tööle hakkab, tekib vĂ”imalus rÀÀkida ja nii edasi.

Üks tĂ€htis asi on see, et kohtus ĂŒritab vastaspoole advokaat seda sinuga teha – nĂŒĂŒd on juba selge, miks. Sest tal on vĂ”imalus sind survestada sellisesse seisundisse, et sa ei suuda isegi oma nime vĂ€lja öelda, nĂ€iteks. KĂ”ige otsesemas mĂ”ttes, sa ei suuda rÀÀkida. Kui sinuga juhtub midagi sellist ja tead, et satud kohta, kus sĂ”nalised lahingud kĂ€ivad, nĂ€iteks kohtusse, siis on mĂ”istlik tulla oma advokaadiga. Advokaat kaitseb sind ja peatab sĂ”nalise rĂŒnnaku, ning teeb seda tĂ€iesti seaduslikul viisil, ning sul taastub kaotatud zen-ruum. NĂ€iteks, mul oli paar korda vaja perekonnale helistada, kohtunik suhtus sellesse ĂŒsna sĂ”bralikult, kuid vastaspoole advokaat karjus ja karjus mu peale, ma ei suutnud isegi sĂ”na sisse tuua. Sellistes olukordades toimib minu jaoks kĂ”ige paremini vahendaja kasutamine. Vahendaja peatab kogu selle surve, mis voolab sinu peale pideva voona, ning sa avastad vajaliku zen-ruumi, koos sellega taastub ka rÀÀkimise vĂ”ime. See on terve teadmiste valdkond, kus tuleb palju Ă”ppida, palju enda seest avastada, ning kĂ”ik see muutub kĂ”rgetasemelisteks strateegilisteks otsusteks, mis on erinevad erinevate inimeste jaoks. MĂ”nel inimesel pole ĂŒlaltoodud probleeme, tavaliselt pole neid inimestel, kes tegelevad kutseliselt mĂŒĂŒgiga. KĂ”ik need inimesed, kes teenivad elatist sĂ”nadega – tuntud lauljad, luuletajad, usujuhid ja poliitikud, neil on alati, mida öelda. Neil pole selliseid probleeme, aga mul need on.

Andrei: See oli
 ootamatu. SuurepÀrane, me oleme juba piisavalt juttu ajanud ja on aeg see intervjuu lÔpetada. Me kohtume kindlasti konverentsil ja saame seda dialooge jÀtkata. Kohtume Hydral!

Kliiffiga saab vestlust jÀtkata konverentsil Hydra 2019, mis toimub 11-12. juulil 2019 Peterburis. Ta tuleb oma ettekandega «Azul Hardware Transactional Memory kogemus». Pileteid saab osta ametlikul veebilehelt.

Allikas: habr.com

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster