Puikus interviu su Cliff Click, JIT kompiliacijos Java tėvu

Puikus interviu su Cliff Click, JIT kompiliacijos Java tėvuCliff Click — Cratus (IoT jutikliai procesams tobulinti) CTO, kelių startuolių (įskaitant Rocket Realtime School, Neurensic ir H2O.ai) įkūrėjas ir vienas iš įkūrėjų, sėkmingai pasitraukusių iš kelių. Pirmąjį savo kompiliatorių Cliffas parašė būdamas 15 metų (Pascalis TRS Z-80)! Jis geriausiai žinomas dėl savo darbo su C2 Java (mazgų jūroje IR). Šis kompiliatorius parodė pasauliui, kad JIT gali sukurti aukštos kokybės kodą, o tai buvo vienas iš veiksnių, lemiančių Java, kaip vienos iš pagrindinių šiuolaikinių programinės įrangos platformų, atsiradimą. Tada Cliff padėjo „Azul Systems“ sukurti 864 branduolių pagrindinį kompiuterį su gryna „Java“ programine įranga, palaikančia GC pauzes 500 gigabaitų krūvoje per 10 milisekundžių. Apskritai, Cliffui pavyko dirbti su visais JVM aspektais.

 
Šis habrapostas yra puikus interviu su Cliffu. Kalbėsime šiomis temomis:

  • Perėjimas prie žemo lygio optimizavimo
  • Kaip atlikti didelį pertvarkymą
  • Kainos modelis
  • Žemo lygio optimizavimo mokymai
  • Praktiniai veiklos gerinimo pavyzdžiai
  • Kodėl verta kurti savo programavimo kalbą
  • Veiklos inžinieriaus karjera
  • Techniniai iššūkiai
  • Šiek tiek apie registrų paskirstymą ir kelių branduolių
  • Didžiausias iššūkis gyvenime

Interviu veda:

  • Andrejus Satarinas iš Amazon Web Services. Per savo karjerą jis sugebėjo dirbti visiškai skirtinguose projektuose: išbandė NewSQL platinamą duomenų bazę „Yandex“, debesų aptikimo sistemą „Kaspersky Lab“, kelių žaidėjų žaidimą „Mail.ru“ ir užsienio valiutos kainų skaičiavimo paslaugą „Deutsche Bank“. Domina didelio masto backend ir paskirstytų sistemų testavimas.
  • Vladimiras Sitnikovas iš Netcracker. Dešimt metų darbo dėl „NetCracker OS“ našumo ir mastelio – programinės įrangos, kurią telekomunikacijų operatoriai naudoja tinklo ir tinklo įrangos valdymo procesams automatizuoti. Domina Java ir Oracle Database našumo problemos. Daugiau nei tuzino oficialios PostgreSQL JDBC tvarkyklės našumo patobulinimų autorius.

Perėjimas prie žemo lygio optimizavimo

Andrius: Jūs esate didelis vardas JIT kompiliavimo, Java ir apskritai atlikimo darbų pasaulyje, tiesa? 

Cliff: Tai taip!

Andrius: Pradėkime nuo kelių bendrų klausimų apie atlikimo darbą. Ką manote apie aukšto ir žemo lygio optimizavimo pasirinkimą, pvz., darbą procesoriaus lygiu?

Cliff: Taip, čia viskas paprasta. Greičiausias kodas yra tas, kuris niekada nepaleidžiamas. Todėl visada reikia pradėti nuo aukšto lygio, dirbti su algoritmais. Geresnis O žymėjimas įveiks prastesnį O žymėjimą, nebent įsiterptų kai kurios pakankamai didelės konstantos. Žemo lygio dalykai lieka paskutiniai. Paprastai, jei pakankamai gerai optimizavote likusią krūvą ir dar liko įdomių dalykų, tai yra žemas lygis. Bet kaip pradėti nuo aukšto lygio? Kaip žinoti, kad atlikta pakankamai aukšto lygio darbo? Na... jokiu būdu. Paruoštų receptų nėra. Turite suprasti problemą, apsispręsti, ką darysite (kad neimtumėte nereikalingų žingsnių ateityje), tada galėsite atskleisti profiliuotoją, kuris gali pasakyti ką nors naudingo. Tam tikru momentu jūs pats suprantate, kad atsikratėte nereikalingų dalykų ir atėjo laikas atlikti žemo lygio koregavimą. Tai tikrai ypatinga meno rūšis. Daug žmonių daro nereikalingus darbus, bet juda taip greitai, kad neturi laiko nerimauti dėl produktyvumo. Bet tai tol, kol iškils atviras klausimas. Paprastai 99% atvejų niekam nerūpi, ką aš darau, iki to momento, kai kritiniame kelyje atsiranda svarbus dalykas, kuris niekam nerūpi. Ir čia visi pradeda pykti dėl to, „kodėl nuo pat pradžių neveikė idealiai“. Apskritai, našumą visada galima pagerinti. Tačiau 99% atvejų jūs neturite potencialių klientų! Jūs tiesiog stengiatės, kad kažkas pavyktų, o proceso metu išsiaiškinate, kas svarbu. Niekada negali iš anksto žinoti, kad šis kūrinys turi būti tobulas, taigi, tiesą sakant, turi būti tobulas visame kame. Bet tai neįmanoma ir jūs to nedarote. Visada reikia sutvarkyti daugybę dalykų – ir tai visiškai normalu.

Kaip atlikti didelį pertvarkymą

Andrius: Kaip dirbate prie spektaklio? Tai yra visa apimanti problema. Pavyzdžiui, ar kada nors teko spręsti problemas, kylančias dėl daugelio esamų funkcijų sankirtos?

Cliff: Stengiuosi to išvengti. Jei žinau, kad našumas bus problema, pagalvoju apie tai prieš pradėdamas koduoti, ypač su duomenų struktūromis. Tačiau dažnai visa tai atrandi labai vėliau. O tada reikia imtis kraštutinių priemonių ir daryti tai, ką aš vadinu „perrašyti ir užkariauti“: reikia paimti pakankamai didelį gabalą. Dalį kodo vis tiek teks perrašyti dėl našumo problemų ar dar ko nors. Kad ir kokia būtų kodo perrašymo priežastis, beveik visada geriau perrašyti didesnį gabalą nei mažesnį. Šiuo metu visi pradeda drebėti iš baimės: „O Dieve, tu negali liesti tiek kodo! Tačiau iš tikrųjų šis metodas beveik visada veikia daug geriau. Reikia nedelsiant imtis didelės problemos, nubrėžti aplink ją didelį ratą ir pasakyti: aš viską perrašysiu apskritimo viduje. Kraštinė yra daug mažesnė nei jos viduje esantis turinys, kurį reikia pakeisti. O jei toks ribų nubrėžimas leidžia puikiai atlikti darbus viduje, rankos laisvos, daryk ką nori. Kai suprasite problemą, perrašymo procesas bus daug paprastesnis, todėl stenkitės!
Tuo pačiu metu, kai perrašote daug ir suprantate, kad našumas bus problema, galite iškart pradėti dėl to nerimauti. Paprastai tai virsta paprastais dalykais, tokiais kaip „nekopijuokite duomenų, tvarkykite duomenis kuo paprasčiau, sumažinkite jų skaičių“. Didelių perrašymų metu yra standartinių būdų, kaip pagerinti našumą. Ir jie beveik visada sukasi apie duomenis.

Kainos modelis

Andrius: vienoje iš podcast'ų kalbėjote apie sąnaudų modelius produktyvumo kontekste. Ar galite paaiškinti, ką tuo turėjote omenyje?

Cliff: Žinoma. Gimiau epochoje, kai procesoriaus našumas buvo nepaprastai svarbus. Ir vėl grįžta ši era – likimas neapsieina be ironijos. Aš pradėjau gyventi aštuonių bitų mašinų laikais; mano pirmasis kompiuteris dirbo su 256 baitais. Tiksliai baitais. Viskas buvo labai maža. Instrukcijas reikėjo skaičiuoti, o kai pradėjome judėti į viršų programavimo kalbų krūva, kalbos įgavo vis daugiau ir daugiau. Buvo „Assembler“, tada „Basic“, tada „C“, o C rūpinosi daugybe smulkmenų, pavyzdžiui, registro paskirstymu ir instrukcijų pasirinkimu. Bet ten viskas buvo gana aišku, o jei rodyčiau žymeklį į kintamojo egzempliorių, gaučiau apkrovą, o šios instrukcijos kaina yra žinoma. Techninė įranga sukuria tam tikrą skaičių mašinos ciklų, todėl skirtingų dalykų vykdymo greitį galima apskaičiuoti tiesiog sudėjus visas instrukcijas, kurias ketinate vykdyti. Kiekvieną palyginimą / bandymą / filialą / skambutį / įkėlimą / parduotuvę galima susumuoti ir pasakyti: tai yra jūsų vykdymo laikas. Dirbdami su našumo gerinimu tikrai atkreipsite dėmesį į tai, kokie skaičiai atitinka mažus karštus ciklus. 
Tačiau kai tik pereini prie „Java“, „Python“ ir panašių dalykų, labai greitai atsitraukiate nuo žemo lygio aparatinės įrangos. Kiek kainuoja iškviesti getterį Java? Jei JIT HotSpot yra teisingas įdėtas, jis bus įkeltas, bet jei to nepadarė, tai bus funkcijos iškvietimas. Kadangi skambutis vyksta karštuoju ciklu, jis nepaisys visų kitų to ciklo optimizacijų. Todėl realios išlaidos bus daug didesnės. Ir jūs iš karto prarandate galimybę pažvelgti į kodo fragmentą ir suprasti, kad turėtume jį vykdyti pagal procesoriaus laikrodžio greitį, naudojamą atmintį ir talpyklą. Visa tai tampa įdomu tik tada, kai iš tikrųjų patenki į spektaklį.
Dabar atsidūrėme situacijoje, kai procesoriaus greitis beveik nepadidėjo dešimtmetį. Seni laikai grįžta! Nebegalite tikėtis gero vienos gijos našumo. Bet jei staiga įsitrauki į lygiagretųjį skaičiavimą, tai bus nepaprastai sunku, visi į tave žiūri kaip į Džeimsą Bondą. Dešimteriopai pagreičiai čia dažniausiai būna tose vietose, kur kažkas kažką sujaukė. Suderinamumas reikalauja daug darbo. Norėdami gauti XNUMX kartų pagreitį, turite suprasti sąnaudų modelį. Kas ir kiek kainuoja? Ir norėdami tai padaryti, turite suprasti, kaip liežuvis priglunda prie pagrindinės įrangos.
Martinas Thompsonas savo tinklaraščiui pasirinko puikų žodį Mechaninė simpatija! Turite suprasti, ką aparatinė įranga darys, kaip tiksliai ji tai darys ir kodėl ji daro tai, ką daro. Naudojant tai, gana lengva pradėti skaičiuoti instrukcijas ir išsiaiškinti, kur eina vykdymo laikas. Jei neturite tinkamo mokymo, jūs tiesiog ieškote juodos katės tamsiame kambaryje. Matau žmones, kurie nuolat optimizuoja našumą, kurie net neįsivaizduoja, ką jie daro. Jie daug kenčia ir nedaro didelės pažangos. Ir kai paimu tą patį kodo fragmentą, paslydžiu porą mažų įsilaužimų ir penkis ar dešimt kartų padidinu greitį, jie tarsi: na, tai neteisinga, mes jau žinojome, kad tu geresnis. Nuostabu. Apie ką aš kalbu... kaštų modelis yra apie tai, kokį kodą rašai ir kaip jis vidutiniškai veikia dideliame paveiksle.

Andrius: O kaip galvoje išlaikyti tokį apimtį? Ar tai pasiekiama turint daugiau patirties, ar? Iš kur tokia patirtis?

Cliff: Na, patirties gavau ne pačiu lengviausiu būdu. Aš programavau Assembly tais laikais, kai galėjai suprasti kiekvieną nurodymą. Skamba kvailai, bet nuo tada Z80 instrukcijų rinkinys visada išliko mano galvoje, atmintyje. Nepamenu žmonių vardų per minutę po pokalbio, bet prisimenu kodą, parašytą prieš 40 metų. Tai juokinga, atrodo kaip sindromas "idiotas mokslininkas".

Žemo lygio optimizavimo mokymai

Andrius: Ar yra lengvesnis būdas patekti?

Cliff: Taip ir ne. Mūsų visų naudojama aparatinė įranga laikui bėgant nepasikeitė. Visi naudoja x86, išskyrus Arm išmaniuosius telefonus. Jei nedarote kažkokio sudėtingo įterpimo, darote tą patį. Gerai, toliau. Instrukcijos taip pat nesikeitė šimtmečius. Turite eiti ir parašyti ką nors Asamblėjoje. Nedaug, bet pakankamai, kad pradėčiau suprasti. Tu šypsaisi, bet aš kalbu visiškai rimtai. Turite suprasti kalbos ir aparatinės įrangos atitikimą. Po to jums reikia eiti, parašyti šiek tiek ir padaryti nedidelį žaislų kompiliatorių, skirtą mažai žaislų kalbai. Panašus į žaislą reiškia, kad jį reikia pagaminti per protingą laiką. Tai gali būti labai paprasta, tačiau ji turi generuoti instrukcijas. Instrukcijos generavimas padės suprasti sąnaudų modelį tarp aukšto lygio kodo, kurį visi rašo, ir mašinos kodo, veikiančio aparatinėje įrangoje. Ši korespondencija bus įrašyta į smegenis tuo metu, kai bus parašytas kompiliatorius. Net ir paprasčiausias kompiliatorius. Po to galima pradėti žiūrėti į Java ir tai, kad jos semantinė bedugnė yra daug gilesnė, o tiltus per ją nutiesti daug sunkiau. Javoje daug sunkiau suprasti, ar mūsų tiltas pasirodė geras ar blogas, dėl ko jis subyrės, o kas ne. Bet jums reikia tam tikro atspirties taško, kuriame pažvelgtumėte į kodą ir suprastumėte: „Taip, šis geteris turėtų būti įtrauktas kiekvieną kartą“. Ir tada paaiškėja, kad kartais taip nutinka, išskyrus situaciją, kai metodas tampa per didelis ir JIT pradeda viską inlinuoti. Tokių vietų našumą galima nuspėti akimirksniu. Paprastai geteriai veikia gerai, bet tada žiūrite į dideles karštąsias kilpas ir suprantate, kad ten sklando funkcijų iškvietimai, kurie nežino, ką daro. Tai yra plačiai paplitusio geterių naudojimo problema, todėl jie nėra įtraukti, nes neaišku, ar jie yra geteriai. Jei turite labai mažą kodo bazę, galite tiesiog ją prisiminti ir pasakyti: tai yra geteris, o tai yra seteris. Didelėje kodų bazėje kiekviena funkcija gyvena savo istoriją, kuri apskritai niekam nėra žinoma. Profiliuotojas sako, kad mes praradome 24% laiko tam tikroje kilpoje ir norėdami suprasti, ką ši kilpa daro, turime pažvelgti į kiekvieną funkciją viduje. Neįmanoma to suprasti neištyrus funkcijos, o tai labai sulėtina supratimo procesą. Štai kodėl aš nenaudoju geterių ir seterių, pasiekiau naują lygį!
Kur gauti išlaidų modelį? Na, ką nors perskaityti, žinoma... Bet aš manau, kad geriausias būdas yra veikti. Sukurti nedidelį kompiliatorių bus geriausias būdas suprasti sąnaudų modelį ir pritaikyti jį savo galvai. Nedidelis kompiliatorius, kuris tiktų mikrobangų krosnelei programuoti – pradedančiojo užduotis. Na, turiu galvoje, jei jau turite programavimo įgūdžių, tada to turėtų pakakti. Visi šie dalykai, pavyzdžiui, eilutės, kurią turite kaip tam tikrą algebrinę išraišką, analizavimas, matematinių operacijų instrukcijų ištraukimas iš ten teisinga tvarka, teisingų reikšmių paėmimas iš registrų - visa tai daroma vienu metu. Ir kol tai darysite, tai bus įspausta jūsų smegenyse. Manau, kad visi žino, ką daro kompiliatorius. Ir tai leis suprasti išlaidų modelį.

Praktiniai veiklos gerinimo pavyzdžiai

Andrius: Į ką dar reikėtų atkreipti dėmesį dirbant su produktyvumu?

Cliff: Duomenų struktūros. Beje, taip, aš jau seniai nevedau šių pamokų... Raketų mokykla. Buvo smagu, bet reikėjo įdėti daug pastangų, o aš taip pat turiu gyvenimą! GERAI. Taigi vienoje iš didelių ir įdomių užsiėmimų „Kur dingsta jūsų našumas“ pateikiau studentams pavyzdį: iš CSV failo buvo nuskaityti du su puse gigabaito „fintech“ duomenų ir tada jie turėjo apskaičiuoti parduotų produktų skaičių. . Reguliarūs erkių rinkos duomenys. UDP paketai konvertuoti į teksto formatą nuo 70-ųjų. Čikagos prekių birža – visokie dalykai, pavyzdžiui, sviestas, kukurūzai, sojos pupelės ir panašūs dalykai. Reikėjo suskaičiuoti šiuos produktus, operacijų skaičių, vidutinę lėšų ir prekių judėjimo apimtį ir kt. Tai gana paprasta prekybos matematika: suraskite produkto kodą (tai yra 1–2 simboliai maišos lentelėje), gaukite sumą, pridėkite ją prie vieno iš prekybos rinkinių, pridėkite apimtį, pridėkite vertę ir dar keletą dalykų. Labai paprasta matematika. Žaislo įgyvendinimas buvo labai nesudėtingas: viskas yra faile, aš skaitau failą ir judu per jį, skirstydamas atskirus įrašus į Java eilutes, ieškau juose reikalingų dalykų ir juos sudedu pagal aukščiau aprašytą matematiką. Ir veikia nedideliu greičiu.

Taikant šį metodą akivaizdu, kas vyksta, o lygiagretusis skaičiavimas nepadės, tiesa? Pasirodo, penkis kartus padidinti našumą galima tiesiog pasirinkus tinkamas duomenų struktūras. Ir tai stebina net patyrusius programuotojus! Mano konkrečiu atveju gudrybė buvo ta, kad neturėtumėte skirti atminties per karštą kilpą. Na, tai ne visa tiesa, bet apskritai - nereikėtų paryškinti „vieną kartą X“, kai X yra pakankamai didelis. Kai X yra du su puse gigabaito, neturėtumėte skirti nieko „vieną kartą raidėje“, „vieną kartą eilutėje“, „vieną kartą lauke“, nieko panašaus. Čia ir praleidžiamas laikas. Kaip tai net veikia? Įsivaizduokite, kad skambinu String.split() arba BufferedReader.readLine(). Readline sukuria eilutę iš baitų, atėjusių per tinklą, po vieną kiekvienai eilutei, kiekvienai iš šimtų milijonų eilučių. Aš paimu šią eilutę, analizuoju ir išmetu. Kodėl aš jį išmetu - gerai, aš jau jį apdorojau, tai viskas. Taigi už kiekvieną baitą, nuskaitytą iš šių 2.7G, eilutėje bus įrašyti du simboliai, tai yra jau 5.4G, ir man jų niekam nereikia, todėl jie išmetami. Jei pažiūrėsite į atminties pralaidumą, tai įkrauname 2.7G, kuris eina per atmintį ir atminties magistralę procesoriuje, o tada į atmintyje gulinčią eilutę siunčiama dvigubai daugiau, ir visa tai nutrinama kuriant kiekvieną naują eilutę. Bet man reikia jį perskaityti, aparatinė įranga skaito, net jei vėliau viskas sutrinka. Ir turiu užsirašyti, nes sukūriau eilutę ir talpyklos pilnos – talpykloje netalpina 2.7G. Taigi, už kiekvieną perskaitytą baitą aš perskaitau dar du baitus ir parašau dar du baitus, ir galiausiai jie turi 4:1 santykį – tokiu santykiu eikvojame atminties pralaidumą. Ir tada paaiškėja, kad jei aš tai padarysiu String.split() – tai darau ne paskutinį kartą, viduje gali būti dar 6-7 laukai. Taigi klasikinis CSV skaitymo ir eilučių analizavimo kodas lemia maždaug 14:1 atminties pralaidumo eikvojimą, palyginti su tuo, ko iš tikrųjų norėtumėte turėti. Jei išmesite šiuos pasirinkimus, galite pagreitinti penkis kartus.

Ir tai nėra taip sunku. Jei pažvelgsite į kodą tinkamu kampu, supratus problemą, viskas taps gana paprasta. Nereikėtų visiškai nustoti skirstyti atminties: vienintelė problema yra ta, kad kažką paskirstote ir jis iškart miršta, o pakeliui sudegina svarbų resursą, kuris šiuo atveju yra atminties pralaidumas. Ir visa tai lemia produktyvumo kritimą. x86 paprastai reikia aktyviai įrašyti procesoriaus ciklus, tačiau čia visą atmintį sudeginote daug anksčiau. Išeitis – sumažinti išskyrų kiekį. 
Kita problemos dalis yra ta, kad jei paleidžiate profiliavimo programą, kai baigiasi atminties juosta, tada, kai taip nutinka, dažniausiai laukiate, kol atkurta talpykla, nes joje pilna šiukšlių, kurias ką tik sukūrėte, visos tos eilutės. Todėl kiekvienas įkėlimas ar parduotuvės operacija tampa lėta, nes jos veda prie talpyklos praleidimų – visa talpykla sulėtėjo, laukia, kol iš jos išeis šiukšlės. Todėl profiliuotojas tiesiog rodys šiltą atsitiktinį triukšmą, išteptą per visą kilpą – atskiros karštos instrukcijos ar vietos kode nebus. Tik triukšmas. O jei pažiūrėtumėte į GC ciklus, tai visi jie yra jaunosios kartos ir itin greiti – mikrosekundžių ar milisekundžių maksimumas. Juk visas šis prisiminimas akimirksniu miršta. Jūs skiriate milijardus gigabaitų, o jis juos supjausto, supjausto ir dar kartą. Visa tai vyksta labai greitai. Pasirodo, kad yra pigūs GC ciklai, šiltas triukšmas per visą ciklą, bet mes norime gauti 5x pagreitį. Šią akimirką kažkas turėtų užsidaryti galvoje ir skambėti: "kodėl taip?!" Atminties juostos perpildymas nerodomas naudojant klasikinį derintuvą; turite paleisti aparatūros našumo skaitiklio derinimo priemonę ir pamatyti ją patys bei tiesiogiai. Tačiau iš šių trijų simptomų to tiesiogiai įtarti negalima. Trečias simptomas yra tada, kai žiūrite į tai, ką pabrėžiate, paklauskite profiliuotojo ir jis atsako: „Jūs padarėte milijardą eilučių, bet GC dirbo nemokamai. Kai tik tai atsitiks, supranti, kad sukūrėte per daug objektų ir sudeginote visą atminties juostą. Yra būdas tai išsiaiškinti, bet tai nėra akivaizdu. 

Problema yra duomenų struktūroje: plika struktūra, kurioje yra viskas, kas vyksta, ji per didelė, diske yra 2.7 G, todėl daryti šio dalyko kopiją yra labai nepageidautina - norite iš karto įkelti jį iš tinklo baitų buferio į registrus, kad penkis kartus nereikėtų skaityti-rašyti į eilutę pirmyn ir atgal. Deja, Java pagal numatytuosius nustatymus nesuteikia tokios bibliotekos kaip JDK dalies. Bet tai trivialus, tiesa? Iš esmės tai yra 5–10 kodo eilučių, kurios bus naudojamos jūsų pačių buferinės eilutės įkėlimo programai įgyvendinti, kuri pakartoja eilučių klasės elgseną ir kartu yra pagrindinė baitų buferio dalis. Dėl to pasirodo, kad dirbate beveik kaip su eilutėmis, bet iš tikrųjų ten juda rodyklės į buferį, o neapdoroti baitai niekur nenukopijuojami, taigi tie patys buferiai yra naudojami vėl ir vėl, ir operacinė sistema mielai imasi dalykų, kuriems ji skirta, pvz., paslėptą dvigubą šių baitų buferių buferį, ir jūs nebesikraunate begalinio nereikalingų duomenų srauto. Beje, ar suprantate, kad dirbant su GC garantuojama, kad po paskutinio GC ciklo kiekvienas atminties paskirstymas procesoriui nebus matomas? Todėl visa tai negali būti talpykloje ir tada įvyksta 100% garantuotas praleidimas. Dirbant su rodykle, x86, registro atėmimas iš atminties užtrunka 1-2 laikrodžio ciklus, o kai tik tai įvyksta, mokate, mokate, mokate, nes atmintis įjungta DEVYNI talpyklos – ir tai yra atminties paskirstymo kaina. Tikra vertė.

Kitaip tariant, sunkiausia pakeisti duomenų struktūras. Ir kai suprasite, kad pasirinkote netinkamą duomenų struktūrą, kuri vėliau neigiamai paveiks našumą, paprastai turėsite daug nuveikti, bet jei to nepadarysite, viskas pablogės. Visų pirma, reikia galvoti apie duomenų struktūras, tai svarbu. Pagrindinės išlaidos čia tenka riebiosioms duomenų struktūroms, kurios pradedamos naudoti tokiu stiliumi: „Aš nukopijavau duomenų struktūrą X į duomenų struktūrą Y, nes man labiau patinka Y forma“. Tačiau kopijavimo operacija (kuri atrodo pigi) iš tikrųjų eikvoja atminties pralaidumą ir čia palaidotas visas sugaištas vykdymo laikas. Jei turiu milžinišką JSON eilutę ir noriu ją paversti struktūrizuotu POJO DOM medžiu ar pan., šios eilutės analizavimas ir POJO sukūrimas, o vėliau vėl prieiga prie POJO, sukels nereikalingų išlaidų – tai yra nepigus. Išskyrus tuos atvejus, kai aplink POJO bėgioji daug dažniau nei aplink eilutę. Vietoj to galite pabandyti iššifruoti eilutę ir iš jos išgauti tik tai, ko jums reikia, nepaversdami jos jokiu POJO. Jei visa tai vyksta kelyje, nuo kurio reikalingas maksimalus našumas, jums jokių POJO, reikia kažkaip įsigilinti tiesiai į liniją.

Kodėl verta kurti savo programavimo kalbą

Andrius: Sakėte, kad norint suprasti sąnaudų modelį, reikia rašyti savo mažą kalbą...

Cliff: Ne kalba, o kompiliatorius. Kalba ir kompiliatorius yra du skirtingi dalykai. Svarbiausias skirtumas yra jūsų galvoje. 

Andrius: Beje, kiek žinau, jūs eksperimentuojate kurdami savo kalbas. Kam?

Cliff: Nes aš galiu! Esu pusiau pensininkė, todėl tai mano hobis. Visą gyvenimą diegiau kitų kalbas. Taip pat daug dirbau su savo kodavimo stiliumi. Ir dar todėl, kad matau problemų kitose kalbose. Matau, kad yra geresnių būdų daryti pažįstamus dalykus. Ir aš juos naudočiau. Aš tiesiog pavargau matyti problemas savyje, Java, Python ir bet kuria kita kalba. Dabar rašau „React Native“, „JavaScript“ ir „Elm“ kaip hobį, kuris nėra susijęs su išėjimu į pensiją, o apie aktyvų darbą. Taip pat rašau Python ir, greičiausiai, toliau dirbsiu su mašininiu mokymusi, skirtu „Java“ sistemoms. Yra daug populiarių kalbų ir jos visos turi įdomių savybių. Kiekvienas yra geras savaip, ir jūs galite pabandyti sujungti visas šias savybes. Taigi, studijuoju dalykus, kurie mane domina, kalbos elgesį, bandau sugalvoti pagrįstą semantiką. Ir kol kas man sekasi! Šiuo metu kovoju su atminties semantika, nes noriu turėti tokią kaip C ir Java, ir gauti stiprų atminties modelį bei atminties semantiką įkrovimams ir parduotuvėms. Tuo pačiu metu turėkite automatinę tipo išvadą, kaip ir Haskell. Čia aš bandau sumaišyti Haskell tipo išvadas su atminties darbu tiek C, tiek Java. Pavyzdžiui, tai aš darau pastaruosius 2-3 mėnesius.

Andrius: Jei kuriate kalbą, kuri perima geresnius aspektus iš kitų kalbų, ar manote, kad kažkas pasielgs priešingai: pasiims jūsų idėjas ir jas panaudos?

Cliff: Būtent taip atsiranda naujos kalbos! Kodėl Java yra panaši į C? Kadangi C sintaksė buvo gera, kurią visi suprato, o Java buvo įkvėpta šios sintaksės, pridėjus tipo saugą, masyvo ribų tikrinimą, GC, be to, jie patobulino kai kuriuos dalykus iš C. Jie pridėjo savo. Bet jie buvo labai įkvėpti, tiesa? Visi stovi ant pečių prieš tave buvusiems milžinams – taip daroma pažanga.

Andrius: Kaip suprantu, jūsų kalba bus saugi. Ar galvojote įdiegti kažką panašaus į „Rust“ skolinimosi tikrintuvą? Ar žiūrėjai į jį, ką apie jį manai?

Cliff: Na, aš jau seniai rašau C, turėdamas visą šitą mallocą ir nemokamai, ir rankiniu būdu tvarkau visą gyvenimą. Žinote, 90–95% rankiniu būdu valdomo gyvenimo laiko turi tą pačią struktūrą. Ir labai labai skausminga tai daryti rankiniu būdu. Norėčiau, kad sudarytojas tiesiog pasakytų, kas ten vyksta ir ką savo veiksmais pasiekėte. Kai kuriais atvejais skolinimosi tikrintuvas tai atlieka iš karto. Ir ji turėtų automatiškai rodyti informaciją, viską suprasti ir net neapkrauti manęs šio supratimo pateikimu. Ji turi atlikti bent vietinę pabėgimo analizę ir tik jei nepavyksta, tada reikia pridėti tipo anotacijas, kurios apibūdins visą gyvenimą – ir tokia schema yra daug sudėtingesnė nei skolinimosi tikrintuvas ar bet koks esamas atminties tikrintuvas. Pasirinkimas tarp „viskas gerai“ ir „nieko nesuprantu“ - ne, turi būti kažkas geriau. 
Taigi, kaip žmogus, parašęs daug kodo C, manau, kad svarbiausia yra palaikyti automatinį valdymą visą gyvenimą. Man taip pat atsibodo, kiek Java naudoja atminties, o pagrindinis skundas yra GC. Kai skirsite atmintį „Java“, negrąžinsite atminties, kuri buvo vietinė paskutinio GC ciklo metu. To nėra kalbomis, kuriose yra tikslesnis atminties valdymas. Jei paskambinsite malloc, iš karto gausite atmintį, kuri paprastai buvo naudojama. Paprastai atliekate kai kuriuos laikinus dalykus su atmintimi ir iškart grąžinate ją atgal. Ir iš karto grįžta į malloc baseiną, o kitas malloc ciklas jį vėl ištraukia. Todėl tikrasis atminties naudojimas sumažinamas iki gyvų objektų rinkinio tam tikru metu ir nutekėjimų. Ir jei viskas nenuteka visiškai nepadoriai, didžioji dalis atminties atsiduria talpyklose ir procesoriuje, ir tai veikia greitai. Tačiau reikia daug rankinio atminties valdymo su malloc ir nemokamai skambinti tinkama tvarka, tinkamoje vietoje. Rust gali tinkamai su tuo susidoroti pati ir daugeliu atvejų suteikia dar geresnį našumą, nes atminties suvartojimas yra susiaurintas iki dabartinio skaičiavimo, o ne laukiant kito GC ciklo, kad atlaisvintų atmintį. Dėl to gavome labai įdomų būdą pagerinti našumą. Ir gana galingas – turiu galvoje, tokius dalykus dariau apdorodamas „fintech“ duomenis, ir tai leido paspartinti maždaug penkis kartus. Tai gana didelis postūmis, ypač pasaulyje, kuriame procesoriai negreitėja ir mes vis dar laukiame patobulinimų.

Veiklos inžinieriaus karjera

Andrius: Taip pat norėčiau pasiteirauti apie karjerą apskritai. Išgarsėjote atlikdami JIT darbą HotSpot, o tada persikėlėte į Azul, kuri taip pat yra JVM įmonė. Bet jau daugiau dirbome su aparatine nei programine įranga. Ir tada jie staiga perėjo prie didelių duomenų ir mašininio mokymosi, o tada prie sukčiavimo nustatymo. Kaip tai nutiko? Tai labai skirtingos plėtros sritys.

Cliff: Aš programuoju gana ilgą laiką ir sugebėjau lankyti daugybę skirtingų užsiėmimų. Ir kai žmonės sako: „O, tu esi tas, kuris padarė JIT Java!“, visada būna juokinga. Tačiau prieš tai dirbau su PostScript klonu – kalba, kurią Apple kadaise naudojo savo lazeriniams spausdintuvams. O prieš tai dariau Forth kalbos įgyvendinimą. Manau, kad bendra tema man yra įrankių kūrimas. Visą gyvenimą kūriau įrankius, kuriais kiti žmonės rašo savo šaunias programas. Bet aš taip pat dalyvavau kuriant operacines sistemas, tvarkykles, branduolio lygio derinimo priemones, OS kūrimo kalbas, kurios prasidėjo nereikšmingos, bet laikui bėgant tapo vis sudėtingesnės. Tačiau pagrindinė tema vis tiek yra įrankių kūrimas. Didelė mano gyvenimo dalis praėjo tarp Azul ir Sun, ir tai buvo apie Java. Bet kai įstojau į „Big Data“ ir „Mašininį mokymąsi“, vėl užsidėjau savo išgalvotą kepurę ir pasakiau: „O, dabar mes turime nebanalią problemą, vyksta daug įdomių dalykų ir žmonės ką nors daro“. Tai puikus vystymosi kelias.

Taip, man labai patinka paskirstytasis kompiuteris. Mano pirmasis darbas buvo C klasės studentas, prie reklamos projekto. Tai buvo paskirstyta skaičiuojant Zilog Z80 lustuose, kurie rinko duomenis analoginiam OCR, pagamintam tikru analoginiu analizatoriumi. Tai buvo šauni ir visiškai beprotiška tema. Bet buvo nesklandumų, kažkokia dalis nebuvo atpažinta teisingai, todėl reikėjo išimti nuotrauką ir parodyti žmogui, kuris jau mokėjo akimis skaityti ir pranešti, ką sako, todėl buvo darbų su duomenimis, o šie darbai turėjo savo kalbą. Buvo užpakalinė programa, kuri visa tai apdorojo – lygiagrečiai veikia Z80 su veikiančiais vt100 terminalais – po vieną žmogui, o Z80 buvo lygiagretus programavimo modelis. Tam tikra bendra atminties dalis, kuria dalijasi visi Z80 žvaigždutėje; Galinė plokštė taip pat buvo bendrinama, o pusė RAM buvo bendrai naudojama tinkle, o kita pusė buvo privati ​​arba skirta kažkam kitam. Prasmingai sudėtinga lygiagrečiai paskirstyta sistema su bendra... pusiau bendra atmintimi. Kada tai buvo... Net neprisimenu, kažkur 80-ųjų viduryje. Gana seniai. 
Taip, tarkime, kad 30 metų yra gana senas laikas. Problemos, susijusios su paskirstytu skaičiavimu, egzistuoja gana seniai, žmonės jau seniai kariavo su Beowulf- klasteriai. Tokie klasteriai atrodo kaip... Pvz.: yra eternetas ir tavo greitasis x86 yra prijungtas prie šio eterneto, o dabar nori gauti netikrą bendrinamą atmintį, nes tada niekas negalėjo atlikti paskirstyto skaičiavimo kodavimo, buvo per sunku ir todėl buvo netikra bendra atmintis su apsaugos atminties puslapiais x86, o jei rašėte į šį puslapį, mes pasakėme kitiems procesoriams, kad jei jie prisijungs prie tos pačios bendrosios atminties, ją reikės įkelti iš jūsų, taigi kažkas panašaus į palaikymo protokolą. atsirado talpyklos darna ir tam skirta programinė įranga. Įdomi koncepcija. Tikroji problema, žinoma, buvo kažkas kita. Visa tai pavyko, tačiau greitai susidarėte našumo problemų, nes niekas nesuprato našumo modelių pakankamai geru lygiu – kokie buvo atminties prieigos šablonai, kaip įsitikinti, kad mazgai be galo nepinguoja vienas kito ir pan.

Tai, ką aš sugalvojau H2O, yra tai, kad patys kūrėjai yra atsakingi už nustatymą, kur paralelizmas paslėptas, o kur ne. Aš sugalvojau kodavimo modelį, dėl kurio didelio našumo kodo rašymas buvo lengvas ir paprastas. Bet rašyti lėtai veikiantį kodą sunku, jis atrodys blogai. Reikia rimtai pabandyti rašyti lėtą kodą, teks naudoti nestandartinius metodus. Stabdymo kodas matomas iš pirmo žvilgsnio. Dėl to dažniausiai rašote greitai veikiantį kodą, tačiau turite išsiaiškinti, ką daryti bendrosios atminties atveju. Visa tai yra susieta su dideliais masyvais ir elgesys ten yra panašus į nepastovius didelius masyvus lygiagrečioje „Java“. Turiu galvoje, įsivaizduokite, kad dvi gijos rašo į lygiagrečią masyvą, viena iš jų laimi, o kita atitinkamai pralaimi, ir jūs nežinote, kuri iš jų yra kuri. Jei jie nėra nepastovi, tada tvarka gali būti kokia tik norite – ir tai veikia tikrai gerai. Žmonėms tikrai rūpi operacijų tvarka, jie deda nepastovius elementus tinkamose vietose ir tikisi, kad su atmintimi susijusių našumo problemų bus tinkamose vietose. Priešingu atveju jie paprasčiausiai parašytų kodą kilpų pavidalu nuo 1 iki N, kur N yra keli trilijonai, tikėdamiesi, kad visi sudėtingi atvejai automatiškai taps lygiagrečiai – ir tai neveikia. Tačiau H2O tai nėra nei Java, nei Scala; jei norite, galite tai laikyti „Java minus minus“. Tai labai aiškus programavimo stilius ir panašus į paprasto C arba Java kodo rašymą su kilpomis ir masyvais. Tačiau tuo pačiu metu atmintis gali būti apdorojama terabaitais. Aš vis dar naudoju H2O. Kartkartėmis jį naudoju įvairiuose projektuose – ir vis tiek tai greičiausias dalykas, dešimtis kartų greitesnis už konkurentus. Jei darote „Big Data“ naudodami stulpelių duomenis, labai sunku įveikti H2O.

Techniniai iššūkiai

Andrius: Koks buvo jūsų didžiausias iššūkis per visą jūsų karjerą?

Cliff: Ar mes aptariame techninę ar ne techninę klausimo dalį? Sakyčiau, didžiausi iššūkiai nėra techniniai. 
Kalbant apie techninius iššūkius. Aš juos tiesiog nugalėjau. Net nežinau, koks buvo didžiausias, bet buvo gana įdomių, kurioms prireikė nemažai laiko, psichinės kovos. Kai nuėjau į Sun, buvau tikras, kad padarysiu greitą kompiliatorių, o būrys senjorų atsakė, kad man niekada nepavyks. Bet aš nuėjau šiuo keliu, parašiau kompiliatorių į registro skirstytuvą ir tai buvo gana greita. Jis buvo toks pat greitas kaip šiuolaikinis C1, tačiau skirstytuvas tada buvo daug lėtesnis, o vėliau tai buvo didelė duomenų struktūros problema. Man jo prireikė rašant grafinį registrų skirstytuvą ir nesupratau dilemos tarp kodo išraiškingumo ir greičio, kuris egzistavo tuo metu ir buvo labai svarbus. Paaiškėjo, kad duomenų struktūra paprastai viršija to meto x86s talpyklos dydį, todėl, jei iš pradžių maniau, kad registrų skirstytuvas išnaudos 5-10 procentų viso drebėjimo laiko, tai iš tikrųjų pasirodė 50 proc.

Laikui bėgant, kompiliatorius tapo švaresnis ir efektyvesnis, dažniau nustojo generuoti baisų kodą, o našumas vis labiau pradėjo panašėti į tai, ką gamina C kompiliatorius. Nebent, žinoma, parašysite kažkokį šūdą, kurio net C nepagreitina. . Jei rašysite kodą, pvz., C, daugiau atvejų gausite tokį našumą kaip C. Ir kuo toliau, tuo dažniau gauni kodą, kuris asimptotiškai sutampa su C lygiu, registrų skirstytuvas pradėjo atrodyti kaip kažkas užbaigtas... nesvarbu, ar tavo kodas veikia greitai ar lėtai. Aš toliau dirbau su skirstytuvu, kad būtų galima geriau pasirinkti. Jis tapo vis lėtesnis ir lėtesnis, tačiau vis geriau pasirodė tais atvejais, kai niekas kitas negalėjo susidoroti. Galėčiau pasinerti į registrų skirstytuvą, palaidoti ten mėnesį darbo ir staiga visas kodas pradėtų vykdyti 5% greičiau. Taip nutikdavo karts nuo karto ir registro skirstytuvas tapo kažkokiu meno kūriniu – visi mėgo ar nekentė, o akademijos žmonės klausinėjo tema „kodėl viskas taip daroma“, kodėl gi ne. linijos nuskaitymas, ir koks skirtumas. Atsakymas vis tiek tas pats: skirstytuvas, pagrįstas grafiko spalvinimu ir labai kruopštus darbas su buferiniu kodu, yra lygus pergalės ginklui, geriausiam deriniui, kurio niekas negali nugalėti. Ir tai gana neakivaizdus dalykas. Visa kita, ką ten daro kompiliatorius, yra gana gerai išstudijuoti dalykai, nors jie taip pat buvo perkelti į meno lygį. Visada dariau dalykus, kurie turėjo paversti kompiliatorių meno kūriniu. Bet tai nebuvo kažkas nepaprasto, išskyrus registro skirstytuvą. Gudrybė yra būti atsargiam Nupjauti esant apkrovai ir, jei taip atsitiks (jei domina, galiu paaiškinti plačiau), tai reiškia, kad galite įsitraukti agresyviau, nerizikuodami nukristi per spektaklio tvarkaraštį. Tais laikais buvo krūva pilno masto kompiliatorių, pakabintų niekučiais ir švilpukais, kurie turėjo registrų skirstytuvus, bet niekas kitas to negalėjo padaryti.

Problema ta, kad jei pridėsite metodus, kuriems taikomas įterpimas, padidinimas ir įterpimo plotas, naudojamų verčių rinkinys akimirksniu viršija registrų skaičių ir jūs turite juos sumažinti. Kritinis lygis dažniausiai ateina tada, kai skirstytuvas pasiduoda, o vienas geras kandidatas išsiliejimui yra vertas kito, parduosite kai kuriuos paprastai laukinius dalykus. Inlining vertė yra ta, kad prarandate dalį pridėtinių išlaidų, pridėtinių skambinimo ir taupymo išlaidų, galite matyti viduje esančias reikšmes ir toliau jas optimizuoti. Inlining kaina yra ta, kad susidaro daug gyvų verčių, o jei jūsų registro skirstytuvas sudega daugiau nei reikia, jūs iš karto prarandate. Todėl dauguma skirstytuvų turi problemą: kai įdėklas kerta tam tikrą liniją, viskas pasaulyje pradedama mažinti ir produktyvumas gali būti nuleistas į tualetą. Tie, kurie įdiegia kompiliatorių, prideda šiek tiek euristikos: pavyzdžiui, nustoti įterpti, pradedant nuo pakankamai didelio dydžio, nes paskirstymai viską sugadins. Taip susidaro kreivė atlikimo grafike – eilute, eilute, pasirodymas pamažu auga – ir tada bumas! – nukrenta kaip greitas domkratas, nes tu per daug išklojai. Taip viskas veikė iki Java atsiradimo. „Java“ reikalauja daug daugiau inliningo, todėl turėjau padaryti savo skirstytuvą daug agresyvesnį, kad jis išsilygintų, o ne strigtų, o jei įterpiate per daug, jis pradeda išsilieti, bet tada vis tiek ateina „nebesiliejimo“ momentas. Tai įdomus pastebėjimas ir jis man pasirodė iš niekur, neaiškus, bet pasiteisino. Ėmiau agresyvaus inliningo ir jis nuvedė mane į vietas, kur Java ir C našumas veikia greta. Jie tikrai artimi – galiu parašyti Java kodą, kuris yra žymiai greitesnis už C kodą ir panašius dalykus, bet iš esmės jie yra maždaug palyginami. Manau, kad dalis šio nuopelno yra registro skirstytuvas, leidžiantis man įterpti kuo kvailiau. Aš tiesiog įtraukiu viską, ką matau. Čia kyla klausimas, ar skirstytuvas veikia gerai, ar rezultatas yra protingai veikiantis kodas. Tai buvo didelis iššūkis: visa tai suprasti ir priversti tai veikti.

Šiek tiek apie registrų paskirstymą ir kelių branduolių

Vladimiras: Tokios problemos kaip registro paskirstymas atrodo kaip kažkokia amžina, nesibaigianti tema. Įdomu, ar kada nors buvo kilusi idėja, kuri atrodė daug žadanti, o vėliau žlugo praktiškai?

Cliff: Žinoma! Registro paskirstymas yra sritis, kurioje bandote rasti euristikos metodus, kad išspręstumėte NP užbaigtą problemą. Ir jūs niekada negalite pasiekti tobulo sprendimo, tiesa? Tai tiesiog neįmanoma. Žiūrėkite, Ahead of Time kompiliacija – ji taip pat veikia prastai. Pokalbis čia yra apie kai kuriuos vidutinius atvejus. Apie tipinį našumą, kad galėtumėte eiti ir pamatuoti ką nors, kas, jūsų manymu, yra geras tipinis našumas – juk jūs stengiatės jį pagerinti! Registrų paskirstymas yra tema, susijusi su našumu. Gavus pirmąjį prototipą, jis veikia ir nudažo tai, ko reikia, prasideda atlikimo darbai. Reikia išmokti gerai matuoti. Kodėl tai svarbu? Jei turite aiškių duomenų, galite pažvelgti į skirtingas sritis ir pamatyti: taip, čia tai padėjo, bet čia viskas sugedo! Kyla keletas gerų idėjų, pridedate naują euristiką ir staiga viskas pradeda veikti šiek tiek geriau. Arba neprasideda. Turėjau aibę atvejų, kai kovojome už penkių procentų našumą, kuris išskyrė mūsų vystymąsi nuo ankstesnio skirstytojo. Ir kiekvieną kartą tai atrodo taip: kažkur laimi, kai kur pralaimi. Jei turite gerus našumo analizės įrankius, galite rasti prarandančias idėjas ir suprasti, kodėl jos žlunga. Galbūt verta viską palikti taip, kaip yra, o gal rimčiau žiūrėti į patikslinimą, arba išeiti ir dar ką nors taisyti. Tai daugybė dalykų! Aš padariau šį šaunų įsilaužimą, bet man taip pat reikia ir šio, ir šio, ir šio – ir jų bendras derinys suteikia tam tikrų patobulinimų. Ir vienišiai gali nepasisekti. Tai yra atlikimo darbo su NP užbaigtomis problemomis pobūdis.

Vladimiras: Susidaro jausmas, kad tokie dalykai kaip dažymas alokatoriuose yra problema, kuri jau išspręsta. Na, tai nuspręsta už jus, sprendžiant iš to, ką jūs sakote, taigi, ar tai verta tada...

Cliff: Tai nėra išspręsta kaip tokia. Jūs turite tai paversti „išspręstu“. Yra sunkių problemų ir jas reikia spręsti. Kai tai bus padaryta, laikas dirbti su produktyvumu. Į šį darbą reikia žiūrėti atitinkamai – atlikti etalonus, rinkti metrikas, paaiškinti situacijas, kai grįžus prie ankstesnės versijos senasis įsilaužimas vėl pradėjo veikti (arba atvirkščiai, sustojo). Ir nepasiduok, kol ko nors nepasieksi. Kaip jau sakiau, jei yra šaunių idėjų, kurios nepasiteisino, bet idėjų registrų paskirstymo srityje tai yra maždaug begalė. Pavyzdžiui, galite skaityti mokslines publikacijas. Nors dabar ši sritis pradėjo judėti daug lėčiau ir tapo aiškesnė nei jaunystėje. Tačiau šioje srityje dirba begalė žmonių ir visas jų idėjas verta išbandyti, visos jos laukia sparnuose. Ir jūs negalite pasakyti, kokie jie geri, nebent juos išbandysite. Kaip gerai jie integruojasi su viskuo kitu jūsų skirstytuve, nes skirstytuvas daro daug dalykų, o kai kurios idėjos jūsų konkrečiame skirstytuve neveiks, bet kitame skirstytuve jos lengvai pasiteisins. Pagrindinis būdas laimėti skirstytuvą yra ištraukti lėtas medžiagas už pagrindinio kelio ir priversti ją dalytis lėtųjų takų ribose. Taigi, jei norite paleisti GC, pasirinkti lėtą kelią, deoptimizuoti, padaryti išimtį, visa tai – žinote, kad tokie dalykai yra gana reti. O jų tikrai retai pasitaiko, patikrinau. Atliekate papildomą darbą ir tai pašalina daug apribojimų šiuose lėtuose keliuose, tačiau tai nėra labai svarbu, nes jie lėti ir retai važiuojami. Pavyzdžiui, nulinė rodyklė – tai niekada neįvyksta, tiesa? Skirtingiems dalykams reikia turėti kelis kelius, tačiau jie neturėtų trukdyti pagrindiniam. 

Vladimiras: Ką manote apie kelių branduolių branduolius, kai vienu metu yra tūkstančiai branduolių? Ar tai naudingas dalykas?

Cliff: GPU sėkmė rodo, kad jis yra gana naudingas!

Vladimiras: Jie yra gana specializuoti. O kaip su bendrosios paskirties procesoriais?

Cliff: Na, tai buvo Azul verslo modelis. Atsakymas atėjo epochoje, kai žmonės labai mėgo nuspėjamą našumą. Tuo metu buvo sunku parašyti lygiagretų kodą. H2O kodavimo modelis yra labai keičiamas, tačiau tai nėra bendros paskirties modelis. Galbūt šiek tiek bendresnis nei naudojant GPU. Ar mes kalbame apie tokio dalyko kūrimo sudėtingumą, ar jo naudojimo sudėtingumą? Pavyzdžiui, Azulas man išmokė įdomią pamoką, gana neakivaizdžią: mažos talpyklos yra normalu. 

Didžiausias iššūkis gyvenime

Vladimiras: O kaip su netechniniais iššūkiais?

Cliff: Didžiausias iššūkis buvo nebūti... maloniam ir maloniam žmonėms. Ir dėl to nuolat atsidurdavau itin konfliktinėse situacijose. Tie, kuriuose žinojau, kad viskas klostosi ne taip, bet nežinojau, kaip elgtis su tomis problemomis, ir negalėjau su jomis susitvarkyti. Taip iškilo daug ilgalaikių, dešimtmečius besitęsiančių problemų. Tai, kad Java turi C1 ir C2 kompiliatorius, yra tiesioginė to pasekmė. Tai, kad dešimt metų iš eilės „Java“ nebuvo kelių lygių kompiliacijos, taip pat yra tiesioginė pasekmė. Akivaizdu, kad mums reikėjo tokios sistemos, bet neaišku, kodėl jos nebuvo. Turėjau problemų su vienu inžinieriumi... arba su grupe inžinierių. Kažkada, kai pradėjau dirbti „Sun“, buvau... Gerai, ne tik tada, aš apskritai visada apie viską turiu savo nuomonę. Ir aš maniau, kad tai tiesa, kad tu gali tiesiog paimti šią savo tiesą ir pasakyti ją tiesiai. Juolab kad didžiąją laiko dalį buvau šokiruojamai teisi. O jei tau nepatinka toks požiūris... ypač jei tu akivaizdžiai klysti ir darai nesąmones... Apskritai mažai kas galėtų toleruoti tokią bendravimo formą. Nors kai kurie galėtų, kaip aš. Visą savo gyvenimą kūriau remiantis meritokratiniais principais. Jei parodysi ką nors ne taip, aš tuoj atsisuksiu ir pasakysiu: tu pasakei nesąmonę. Tuo pačiu, žinoma, atsiprašau ir visa tai, pažymėsiu nuopelnus, jei tokių bus, ir imsiuosi kitų teisingų veiksmų. Kita vertus, esu šokiruojančiai teisus dėl šokiruojančiai didelio viso laiko procento. Ir tai nelabai veikia santykiuose su žmonėmis. Nesistengiu būti malonus, bet užduodu klausimą tiesiai šviesiai. „Tai niekada neveiks, nes vienas, du ir trys“. Ir jie buvo tokie: „O! Buvo ir kitų pasekmių, į kurias turbūt geriau nekreipti dėmesio: pavyzdžiui, tos, kurios paskatino skyrybas su žmona ir po to dešimties metų depresiją.

Iššūkis – tai kova su žmonėmis, su jų suvokimu, ką tu gali ir ko negali, kas svarbu, o kas ne. Buvo daug iššūkių, susijusių su kodavimo stiliumi. Aš vis dar rašau daug kodo, o tais laikais turėjau net sulėtinti tempą, nes atlikdavau per daug lygiagrečių užduočių ir jas atlikdavau prastai, užuot sutelkęs dėmesį į vieną. Žvelgdamas atgal, parašiau pusę kodo Java JIT komandai, komandai C2. Kitas greičiausias programuotojas rašė perpus lėčiau, kitas perpus lėčiau, ir tai buvo eksponentinis nuosmukis. Septintas žmogus šioje eilėje buvo labai, labai lėtas – taip nutinka visada! Paliečiau daug kodo. Pažiūrėjau, kas ką parašė, be išimties spoksojau į jų kodą, peržiūrėjau kiekvieną iš jų ir vis tiek toliau rašiau daugiau pats nei bet kuris iš jų. Šis požiūris nelabai tinka žmonėms. Kai kuriems žmonėms tai nepatinka. O kai nesusitvarko, prasideda visokie skundai. Pavyzdžiui, man kartą buvo liepta nustoti koduoti, nes rašau per daug kodo ir tai kelia pavojų komandai, o man visa tai atrodė kaip pokštas: bičiuli, jei dings likusi komanda ir aš toliau rašau kodą, tu Prarasiu tik pusę komandų. Kita vertus, jei aš nuolat rašau kodą ir tu prarasi pusę komandos, tai skamba kaip labai blogas valdymas. Niekada apie tai negalvojau, nekalbėjau, bet tai vis tiek buvo kažkur mano galvoje. Galvoje sukosi mintis: „Ar jūs visi juokaujate? Taigi, didžiausia problema buvo aš ir mano santykiai su žmonėmis. Dabar daug geriau suprantu save, ilgą laiką buvau programuotojų komandos vadovas, o dabar tiesiai sakau žmonėms: žinote, aš esu toks, koks esu, ir jums teks su manimi susidoroti – ar gerai, jei stovėsiu čia? O kai pradėjo su tuo susidoroti, viskas pavyko. Tiesą sakant, aš nesu nei blogas, nei geras, neturiu jokių blogų ketinimų ar savanaudiškų siekių, tai tiesiog mano esmė, su tuo reikia kažkaip gyventi.

Andrius: Visai neseniai visi pradėjo kalbėti apie intravertų savimonę ir apskritai minkštuosius įgūdžius. Ką galite pasakyti apie tai?

Cliff: Taip, tokią įžvalgą ir pamoką išmokau skyrybų su žmona. Iš skyrybų išmokau suprasti save. Taip pradėjau suprasti kitus žmones. Supraskite, kaip veikia ši sąveika. Tai vienas po kito paskatino atradimus. Buvo suvokimas, kas aš esu ir ką atstovauju. Ką aš darau: arba esu užsiėmęs užduotimi, arba vengiu konflikto, ar dar kažkas – ir toks savimonės lygis tikrai padeda suvaldyti save. Po to viskas vyksta daug lengviau. Vienas dalykas, kurį atradau ne tik savyje, bet ir kituose programuotojuose, tai nesugebėjimas verbalizuoti minčių, kai esi emocinio streso būsenoje. Pavyzdžiui, tu sėdi koduodamas, tėkmės būsenoje, o tada jie pribėga prie tavęs ir pradeda isteriškai rėkti, kad kažkas sugedo ir dabar prieš tave bus imtasi ekstremalių priemonių. Ir jūs negalite pasakyti nė žodžio, nes esate emocinio streso būsenoje. Įgytos žinios leidžia pasiruošti šiai akimirkai, ją išgyventi ir pereiti prie rekolekcijų plano, po kurio galima kažką daryti. Taigi taip, kai pradedi suprasti, kaip visa tai veikia, tai yra didžiulis įvykis, keičiantis gyvenimą. 
Aš pats nerasdavau tinkamų žodžių, bet prisiminiau veiksmų seką. Esmė ta, kad ši reakcija yra tiek fizinė, tiek žodinė, ir jums reikia erdvės. Tokia erdvė, zen prasme. Būtent tai ir reikia paaiškinti, o tada iškart pasitraukti – grynai fiziškai atsitraukti. Kai tyliu žodžiu, galiu emociškai apdoroti situaciją. Kai adrenalinas pasiekia jūsų smegenis, perjungia jus į kovos ar skrydžio režimą, jūs nebegalite nieko pasakyti, ne - dabar jūs esate idiotas, plakantis inžinierius, nesugebantis tinkamai reaguoti ar net sustabdyti atakos, o užpuolikas yra laisvas. pulti vėl ir vėl. Pirmiausia turite vėl tapti savimi, atgauti kontrolę, išeiti iš „kovok arba bėk“ režimo.

Ir tam mums reikia žodinės erdvės. Tiesiog laisva vieta. Jei iš viso ką nors sakote, galite pasakyti būtent tai, o tada eikite ir tikrai suraskite sau „vietos“: eikite pasivaikščioti į parką, užsidarykite duše - nesvarbu. Svarbiausia yra laikinai atsijungti nuo tos situacijos. Vos tik kelioms sekundėms išsijungiate, kontrolė grįžta, pradedate blaiviai mąstyti. „Gerai, aš nesu kažkoks idiotas, nedarau kvailų dalykų, esu gana naudingas žmogus“. Kai sugebėsite įtikinti save, laikas pereiti prie kito etapo: suprasti, kas atsitiko. Tave užpuolė, užpuolimas kilo iš ten, kur nesitikėjai, tai buvo nesąžininga, niekšiška pasala. Tai yra blogai. Kitas žingsnis – suprasti, kodėl užpuolikui to reikėjo. Tikrai, kodėl? Gal todėl, kad jis pats įsiutęs? Kodėl jis piktas? Pavyzdžiui, dėl to, kad jis pats susisuko ir negali prisiimti atsakomybės? Tai yra būdas atsargiai spręsti visą situaciją. Tačiau tam reikia erdvės manevrams, žodinės erdvės. Pats pirmas žingsnis – nutraukti žodinį kontaktą. Venkite diskusijų žodžiais. Atšaukite tai, kuo greičiau pasitraukite. Jei tai pokalbis telefonu, tiesiog padėkite ragelį – tai įgūdis, kurio išmokau bendraudamas su buvusia žmona. Jei pokalbis niekur nevyksta, tiesiog pasakykite „sudie“ ir padėkite ragelį. Iš kitos pusės telefono: „bla bla bla“, jūs atsakote: „Taip, iki! ir padėkite ragelį. Jūs tiesiog baigsite pokalbį. Po penkių minučių, kai sugrįžta gebėjimas protingai mąstyti, šiek tiek atvėsote, tampa įmanoma galvoti apie viską, kas nutiko ir kas bus toliau. Ir pradėkite formuluoti apgalvotą atsakymą, o ne tik reaguokite iš emocijų. Man savimonės proveržis buvo būtent tai, kad esant emocinei įtampai negaliu kalbėti. Išeiti iš šios būsenos, galvoti ir planuoti, kaip reaguoti ir kompensuoti iškilusias problemas – tai teisingi žingsniai tuo atveju, kai negalite kalbėti. Lengviausias būdas – pabėgti nuo situacijos, kurioje pasireiškia emocinis stresas, ir tiesiog nustoti dalyvauti šiame strese. Po to tampi gebantis mąstyti, kai gali mąstyti, tampi gebantis kalbėti ir pan.

Beje, teisme priešingas advokatas bando tai padaryti su jumis - dabar aišku, kodėl. Nes jis turi savybę tave nuslopinti iki tokios būsenos, kad, pavyzdžiui, net negali ištarti savo vardo. Tikra prasme tu negalėsi kalbėti. Jei taip atsitiks jums ir žinote, kad atsidursite tokioje vietoje, kur vyksta žodiniai mūšiai, pavyzdžiui, teisme, tuomet galite atvykti su savo advokatu. Advokatas stos už jus ir sustabdys žodinį puolimą ir padarys tai visiškai legaliai, o prarasta Zen erdvė grįš jums. Pavyzdžiui, porą kartų teko skambinti šeimai, teisėjas buvo gana draugiškas dėl to, bet priešingas advokatas ant manęs rėkė ir šaukė, aš net negalėjau ištarti žodžio. Tokiais atvejais man geriausiai tinka tarpininko naudojimas. Tarpininkas sustabdo visą šį spaudimą, kuris ištisa srove liejasi ant tavęs, randi reikiamą Zen erdvę, o kartu su ja grįžta ir gebėjimas kalbėti. Tai ištisa žinių sritis, kurioje yra daug ką mokytis, daug ką atrasti savyje ir visa tai virsta aukšto lygio strateginiais sprendimais, kurie skirtingiems žmonėms yra skirtingi. Kai kurie žmonės neturi aukščiau aprašytų problemų; paprastai profesionalūs pardavėjai jų neturi. Visi šie žodžiais gyvenantys žmonės – žinomi dainininkai, poetai, religiniai lyderiai ir politikai, jie visada turi ką pasakyti. Jie neturi tokių problemų, bet aš turiu.

Andrius: Tai buvo... netikėta. Puiku, mes jau daug kalbėjome ir laikas baigti šį interviu. Mes tikrai susitiksime konferencijoje ir galėsime tęsti šį dialogą. Iki pasimatymo Hydra!

Pokalbį su Cliff galite tęsti konferencijoje „Hydra 2019“, kuri vyks 11 metų liepos 12-2019 dienomis Sankt Peterburge. Jis ateis su ataskaita „Azul Hardware Transactional Memory patirtis“. Bilietus galima įsigyti oficialioje svetainėje.

Šaltinis: www.habr.com

Добавить комментарий