{"id":35851,"date":"2019-10-31T22:07:03","date_gmt":"2019-10-31T19:07:03","guid":{"rendered":"https:\/\/prohoster.info\/blog\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java\/"},"modified":"2019-10-31T22:07:03","modified_gmt":"2019-10-31T19:07:03","slug":"bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java","status":"publish","type":"post","link":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java","title":{"rendered":"Veliki intervju s Cliffom Clickom \u2013 ocem JIT kompajliranja u Javi","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Veliki intervju s Cliffom Clickom \u2013 ocem JIT kompajliranja u Javi\" src=\"\/wp-content\/uploads\/2019\/07\/9ea9740ef74c0ae14d334482af115222.png\" style=\"display:block;margin: 0 auto;\" \/><strong>Cliff Click<\/strong> \u2014 CTO of Cratus (IoT sensors for process enhancement), founder and co-founder of several startups (including Rocket Realtime School, Neurensic, and H2O.ai) with multiple successful exits. Cliff wrote his first compiler at age 15 (Pascal for the TRS Z-80)! He is best known for his work on C2 in Java (the Sea of Nodes IR). This compiler showed the world that JIT could produce quality code, which was one of the factors in establishing Java as one of the major modern software platforms. Later, Cliff helped Azul Systems build an 864-core mainframe with software entirely in Java, which managed GC pauses on a 500-gigabyte heap within 10 milliseconds. Overall, Cliff has worked on all aspects of the JVM.<br clear=\"all\"><br \/>\n\u00a0<br \/>\nThis HubPost is a large interview with Cliff. We will discuss the following topics:<\/p>\n<p><\/p>\n<ul>\n<li>Transitioning to low-level optimizations<\/li>\n<li>How to perform large refactoring<\/li>\n<li>Cost model<\/li>\n<li>Learning about low-level optimizations<\/li>\n<li>Practical examples of performance improvement<\/li>\n<li>Why create your own programming language<\/li>\n<li>Career of a performance engineer<\/li>\n<li>Technical challenges<\/li>\n<li>A bit about register allocation and multithreading<\/li>\n<li>The biggest challenge in life<\/li>\n<\/ul>\n<p><\/p>\n<p>The interviewers are:<\/p>\n<p><\/p>\n<ul>\n<li><strong>Andrey Sataryn<\/strong> from Amazon Web Services. In his career, he has worked on a variety of projects: testing a NewSQL distributed database at Yandex, a cloud detection system at Kaspersky Lab, a multiplayer game at Mail.ru, and a currency pricing service at Deutsche Bank. He is interested in testing large-scale backend and distributed systems.<\/li>\n<li><strong>Vladimir Sitnikov<\/strong> from Netcracker. He has worked for ten years on the performance and scalability of NetCracker OS \u2014 software used by telecommunications operators to automate network management processes and network equipment. He is passionate about Java and Oracle Database performance. Author of over a dozen performance improvements in the official PostgreSQL JDBC driver.<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"perehod-k-nizkourovnevym-optimizaciyam\">Transitioning to low-level optimizations<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: You are a well-known figure in the world of JIT compilation, in Java, and in performance work overall, right?\u00a0<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: That's right!<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Let's start with general questions about performance work. What do you think about choosing between high-level and low-level optimizations like working at the CPU level?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Ovdje je sve jednostavno. Najbr\u017ei kod je onaj koji se nikada ne pokre\u0107e. Zato treba uvijek po\u010deti s visoke razine, raditi na algoritmima. Bolja O-oznaka pobijedit \u0107e lo\u0161iju O-oznakui, osim ako se ne uplete neka dovoljno velika konstanta. Niskonivojski aspekti dolaze tek na kraju. Obi\u010dno, ako si dovoljno dobro optimizirao ostatak stoga, a jo\u0161 uvijek ostane ne\u0161to zanimljivo \u2013 to je niska razina. No, kako po\u010deti s visoke razine? Kako znati da je u\u010dinjeno dovoljno posla na visokoj razini? Pa... nikako. Nema gotovih recepata. Treba\u0161 razumjeti problem, odlu\u010diti \u0161to planira\u0161 napraviti (da ne poduzima\u0161 nepotrebne korake), i tek tada mo\u017ee\u0161 izvaditi profajler koji mo\u017ee re\u0107i ne\u0161to korisno. U nekom trenutku sam shvati\u0161 da si se oslobodio nepotrebnog i da je do\u0161lo vrijeme za finu prilagodbu niske razine. To je definitivno posebna vrsta umjetnosti. Mnogi ljudi rade nepotrebne stvari, ali se kre\u0107u tako brzo da nemaju vremena brinuti se o performansama. No to je sve dok pitanje ne postane hitno. Obi\u010dno 99% vremena nikome nije zanimljivo \u010dime se bavim, sve do trenutka kada se na kriti\u010dnom putu ne pojavi va\u017ena stvar koja nekome postane bitna. I tada svi po\u010dinju pitati za\u0161to to od po\u010detka nije radilo savr\u0161eno. Ukratko, uvijek postoji ne\u0161to \u0161to se mo\u017ee pobolj\u0161ati u performansama. No 99% vremena nema\u0161 tragove! Samo poku\u0161ava\u0161 natjerati ne\u0161to da radi i tijekom toga shvati\u0161 \u0161to je va\u017eno. Nikada ne mo\u017ee\u0161 unaprijed znati da taj komadi\u0107 treba biti savr\u0161en, stoga, u su\u0161tini, mora\u0161 biti savr\u0161en u svemu. A to je nemogu\u0107e i ti to ne radi\u0161. Uvijek ima puno stvari koje treba popraviti \u2013 i to je sasvim normalno.<\/p>\n<p><\/p>\n<h1 id=\"kak-delat-bolshoy-refaktoring\">How to perform large refactoring<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Kako radite na performansama? To je usputna problematika. Na primjer, jeste li ikada radili na problemima koji nastaju zbog preklapanja velikog broja ve\u0107 postoje\u0107ih funkcionalnosti?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Poku\u0161avam to izbje\u0107i. Ako znam da \u0107e performanse postati problem, razmi\u0161ljam o tome prije nego \u0161to po\u010dnem kodirati, posebno o strukturama podataka. No, \u010desto otkrijete sve to vrlo kasno. Tada se morate poslu\u017eiti drasti\u010dnim mjerama i raditi ono \u0161to ja nazivam \u00abprepisuj i vladaj\u00bb: trebate obuhvatiti dovoljno veliki dio. Dio koda \u0107ete ionako morati prepisati zbog problema s performansama ili ne\u010deg drugog. Koji god razlog za prepisivanje koda bio, gotovo uvijek je bolje prepisati ve\u0107i dio nego manji. U tom trenutku svi po\u010dnu drhtati od straha: \u00abo bo\u017ee, ne mo\u017eemo dirati toliko koda!\u00bb. No, zapravo, takav pristup gotovo uvijek bolje funkcionira. Treba odmah uhvatiti veliki problem, okru\u017eiti ga velikim krugom i re\u0107i: sve unutar kruga, ja \u0107u prepisati. Granica je svakako mnogo manja od sadr\u017eaja unutar nje koji podlije\u017ee promjeni. I ako takvo ocrtavanje granica omogu\u0107ava da se rad unutar njega odradi savr\u0161eno \u2013 imate slobodne ruke, radite \u0161to god \u017eelite. \u010cim shvatite problem, proces prepisivanja ide mnogo lak\u0161e, stoga grizite ve\u0107i komad!<br \/>\nU isto vrijeme, kada radite prepisivanje velikog dijela i shvatite da \u0107e performanse postati problem, mo\u017eete odmah po\u010deti brinuti o tome. Obi\u010dno to postaje jednostavne stvari poput \u00abne kopirajte podatke, upravljajte podacima \u0161to je jednostavnije mogu\u0107e, u\u010dinite ih manjima\u00bb. U velikim prepisivanjima, postoje standardni na\u010dini za pobolj\u0161anje performansi. I oni se gotovo uvijek vrte oko podataka.<\/p>\n<p><\/p>\n<h1 id=\"model-stoimosti\">Cost model<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: U jednom od podkasta govorili ste o modelima cijena u kontekstu performansi. Mo\u017eete li objasniti \u0161to ste time mislili?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Naravno. Ro\u0111en sam u doba kada je performansa procesora bila izuzetno va\u017ena. I ta era se ponovo vra\u0107a \u2013 sudbina nije li\u0161ena ironije. Po\u010deo sam \u017eivjeti u vremenu osmobitnih ma\u0161ina, moj prvi ra\u010dunar radio je s 256 bajtova. Ba\u0161 bajtova. Sve je bilo jako malo. Trebalo je brojati instrukcije i \u010dim smo po\u010deli napredovati kroz stek programskih jezika, jezici su preuzimali sve vi\u0161e. Bio je Assembler, zatim Basic, pa C, a C je preuzimao rad s mnogim detaljima, poput raspodele registara i pronalaska instrukcija. Ali sve je tu bilo prili\u010dno jasno i ako sam napravio pokaziva\u010d na instancu promenljive, dobijam load, a tro\u0161ak te instrukcije je poznat. Hardver izbacuje poznat broj ma\u0161inskih ciklusa, tako da se brzina izvr\u0161avanja razli\u010ditih stvari mo\u017ee izra\u010dunati jednostavnim sabiranjem svih instrukcija koje planira\u0161 pokrenuti. Svaki compare\/test\/branch\/call\/load\/store mogao se sabrati i re\u0107i: evo ga vreme izvr\u0161avanja. Kada se bavi\u0161 pobolj\u0161anjem u\u010dinka, sigurno \u0107e\u0161 obratiti pa\u017enju na to koji brojevi odgovaraju sitnim vru\u0107im ciklusima.\u00a0<br \/>\nAli \u010dim se prebaci\u0161 na Java, Python i sli\u010dne stvari, jako brzo se udaljava\u0161 od niskonivojskog hardvera. Koliki je tro\u0161ak pozivanja gettera u Javi? Ako JIT u HotSpot sve ispravno <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.openjdk.java.net\/display\/HotSpot\/Inlining\">ubacilo<\/a><\/noindex>, to \u0107e biti load, ali ako to nije u\u010dinio \u2013 bi\u0107e to poziv funkcije. Budu\u0107i da poziv le\u017ei u vru\u0107em ciklusu, on \u0107e poni\u0161titi sve druge optimizacije u tom ciklusu. Stoga \u0107e stvarni tro\u0161ak biti mnogo ve\u0107i. I odmah gubi\u0161 sposobnost gledanja na deo koda i razumevanja \u0161ta nam se isplati izvr\u0161iti u terminima taktne frekvencije procesora, kori\u0161\u0107ene memorije i ke\u0161a. Sve to postaje zanimljivo samo kada se zaista u\u0111e u performanse.<br \/>\nTrenutno smo u situaciji u kojoj brzine procesora gotovo ve\u0107 desetlje\u0107ima ne rastu. Stari dani se vra\u0107aju! Ne mo\u017eete vi\u0161e ra\u010dunati na dobru jednonitnu izvedbu. No, ako se odlu\u010dite za paralelno ra\u010dunanje \u2013 to je nevjerojatno slo\u017eeno, svi vas gledaju kao da ste James Bond. Desetostruka ubrzanja javljaju se tamo gdje je netko ne\u0161to propustio. Paralelizam zahtijeva puno posla. Da biste dobili to desetostruko ubrzanje, morate razumjeti model tro\u0161kova. \u0160to i koliko ko\u0161ta. A za to morate shvatiti kako se jezik uklapa u donji hardver.<br \/>\nMartin Thompson prona\u0161ao je odli\u010dnu rije\u010d za svoj blog <noindex><a rel=\"nofollow\" href=\"https:\/\/mechanical-sympathy.blogspot.com\/\">Mehani\u010dka simpatija<\/a><\/noindex>! Potrebno je razumjeti \u0161to hardver poku\u0161ava napraviti, kako to\u010dno to radi i za\u0161to uop\u0107e radi ono \u0161to radi. Iskori\u0161tavaju\u0107i to, prili\u010dno je lako po\u010deti brojati instrukcije i otkrivati gdje vrijeme izvo\u0111enja odlazi. Ako nemate odgovaraju\u0107u pripremu, samo tra\u017eite crnu ma\u010dku u mra\u010dnoj sobi. Neprestano vi\u0111am ljude koji optimiziraju performanse, a nemaju pojma \u0161to uop\u0107e rade. Veoma se mu\u010de i ne napreduju. A kada uzmem isti komadi\u0107 koda, dodam nekoliko sitnih trikova i dobijem petostruko ili desetostruko ubrzanje, oni ka\u017eu: pa, to nije po\u0161teno, znali smo da si bolji. Fascinantno. O \u010demu sam to\u2026 model tro\u0161kova je o tome kakav kod pi\u0161ete i koliko brzo prosje\u010dno radi u cjelokupnoj slici.<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: I kako zadr\u017eati takav obujam u glavi? To se posti\u017ee velikim iskustvom, zar ne? Gdje se stje\u010de takvo iskustvo?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Pa, svoje iskustvo stekao sam na na\u010din koji nije bio ba\u0161 jednostavan. Programirao sam u Assembleru u vrijeme kada se moglo razumjeti svaka pojedina\u010dna instrukcija. Zvu\u010di glupo, ali od tada mi u glavi, u pam\u0107enju, zauvijek ostao niz instrukcija Z80. Ne sje\u0107am se imena ljudi ve\u0107 minutu nakon razgovora, ali se sje\u0107am koda napisanog prije 40 godina. Smije\u0161no, izgleda kao sindrom \u201e<noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A1%D0%B8%D0%BD%D0%B4%D1%80%D0%BE%D0%BC_%D1%81%D0%B0%D0%B2%D0%B0%D0%BD%D1%82%D0%B0\">nau\u010dnika idiota<\/a><\/noindex>\u00bb.<\/p>\n<p><\/p>\n<h1 id=\"obuchenie-nizkourovnevym-optimizaciyam\">Learning about low-level optimizations<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Postoji li jednostavniji na\u010din da se u\u0111e u to?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Da i ne. Hardver koji svi koristimo se u to vrijeme nije mnogo promijenio. Svi koriste x86, osim pametnih telefona koji koriste Arm. Ako se ne bavi\u0161 nekim hardcore ugra\u0111enim sistemima, ima\u0161 sve isto. Dobro, idemo dalje. Upute se tako\u0111er ve\u0107 dugo nisu mijenjale. Potrebno je oti\u0107i i napisati ne\u0161to na Assembleru. Malo, ali dovoljno da po\u010dne\u0161 razumjeti. Smije\u0161ite se, ali ja govorim sasvim ozbiljno. Treba razumjeti odnos jezika i hardvera. Nakon ovoga treba\u0161 oti\u0107i, napisati malo i napraviti mali igra\u0107i kompajler za mali igra\u0107i jezik.<br \/>\nOdakle uzeti model cijene? Pa, mo\u017ee\u0161 pro\u010ditati ne\u0161to, naravno... Ali mislim da je najbolji na\u010din djelovati. Napraviti mali kompajler i to \u0107e biti najbolji na\u010din da razumije\u0161 model cijene i smjesti\u0161 ga u vlastitu glavu. Mali kompajler koji bi bio koristan za programiranje mikrovalne pe\u0107nice \u2013 to je zadatak za po\u010detnike. Mislim da ako ve\u0107 ima\u0161 programerske vje\u0161tine, trebao bi biti sposoban. Sve te stvari poput parsiranja stringa koji \u0107e biti nekakva algebarska izraza, izvu\u0107i upute matemati\u010dkih operacija u pravom redoslijedu, uzeti to\u010dne vrijednosti iz registara \u2013 sve to se radi lako. I dok to radi\u0161, odjavit \u0107e se u mozgu. Mislim da svi znaju \u010dime se bavi kompajler. I to \u0107e dati razumijevanje modela cijene.<\/p>\n<p><\/p>\n<h1 id=\"prakticheskie-primery-uluchsheniya-proizvoditelnosti\">Practical examples of performance improvement<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Na \u0161to jo\u0161 treba obratiti pa\u017enju pri radu na performansama?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Strukture podataka. Usput, dugo nisam vodio te lekcije\u2026 <noindex>Rocket School<\/noindex>. Bilo je zabavno, ali zahtijevalo je mnogo truda, a imam i svoj \u017eivot! U redu. Dakle, na jednom od velikih i zanimljivih predavanja, \u201eGdje odlazi va\u0161 performans\u201c, dao sam studentima primjer: dva i pol gigabajta fintech podataka \u010ditana iz CSV datoteke, a onda je trebalo izra\u010dunati broj prodanih proizvoda. Obi\u010dni tiker tr\u017ei\u0161ni podaci. UDP paketi, pretvoreni u tekstualni format, od 70-ih. Chicago Mercantile Exchange \u2013 razne stvari poput nafte, kukuruza, soje, itd. Trebalo je prebrojati te proizvode, broj transakcija, prosje\u010dni iznos kretanja sredstava i roba, itd. To je prili\u010dno jednostavna trgova\u010dka matematika: prona\u0107i kod proizvoda (to je 1-2 znaka u hash tablici), dobiti iznos, dodati ga u jedan od setova transakcija, dodati volumen, dodati cijenu, i nekoliko drugih stvari. Vrlo jednostavna matematika. Igra\u010dka implementacija bila je vrlo jednostavna: sve je bilo u datoteci, \u010ditam datoteku i kre\u0107em se kroz nju, dijele\u0107i pojedina\u010dne zapise na Java stringove, tra\u017eim potrebne stvari i zbrajam prema gore opisanoj matematici. I to radi s nekakvom malom brzinom. <\/p>\n<p><\/p>\n<p>S ovim pristupom sve je jasno \u0161to se doga\u0111a, a paralelno ra\u010dunarstvo ovdje ne poma\u017ee, zar ne? Ispostavilo se da se petostruko pove\u0107anje performansi mo\u017ee posti\u0107i samo odabirom pravih struktura podataka. To \u010dak iznena\u0111uje i iskusne programere! U mom konkretnom slu\u010daju, fokus je bio na tome da ne trebamo alocirati memoriju unutar vru\u0107e petlje. Pa, to nije cijela istina, ali u su\u0161tini - ne treba alocirati \"jednom u X\", kada je X dovoljno velik. Kada je X dva i pol gigabajta, ne treba alocirati ni\u0161ta \"jednom za slovo\", \"jednom za redak\", ili \"jednom za polje\", ni\u0161ta sli\u010dno. Na to se tro\u0161i vrijeme. Kako to uop\u0107e funkcionira? Zamislite da radim poziv <code>String.split()<\/code> ili <code>BufferedReader.readLine()<\/code>. <code>Readline<\/code> stvara niz od niza bajtova koji dolaze putem mre\u017ee, jednom za svaki redak, za svaki od stotina milijuna redaka. Uzimam ovaj redak, analiziram ga i odbacujem. Za\u0161to ga odbacujem - pa, ve\u0107 sam ga obradio, to je to. Tako da, za svaki bajt pro\u010ditanih iz tih 2.7G, zabilje\u017eit \u0107e se dva znaka u nizu, \u0161to zna\u010di ve\u0107 5.4G, i vi\u0161e mi nisu potrebni, pa se odbacuju. Ako pogledamo propusnost memorije, u\u010ditavamo 2.7G, koje prolaze kroz memoriju i memorijsku sabirnicu u procesoru, a zatim se dvostruko vi\u0161e \u0161alje u niz koji le\u017ei u memoriji, i sve se to obra\u0111uje pri kreiranju svake nove niza. Ali moram ga pro\u010ditati, hardver ga \u010dita, \u010dak i ako \u0107e kasnije sve biti obra\u0111eno. I moram ga zapisati jer sam stvorio niz, a cache-vi su se napunili - cache ne mo\u017ee primiti 2.7G. U kona\u010dnici, za svaki pro\u010ditani bajt, \u010ditam jo\u0161 dva dodatna bajta i zapisujem dva dodatna bajta, i na kraju to ima omjer 4:1 - u takvom omjeru bespotrebno tro\u0161imo propusnost memorije. A onda se ispostavi da ako radim <code>String.split()<\/code> \u2013 to radim daleko od posljednjeg puta, unutra mo\u017ee biti jo\u0161 6-7 polja. Stoga, klasi\u010dni kod za \u010ditanje CSV s kasnijim analizom redaka dovodi do gubitaka propusnosti memorije oko 14:1 u odnosu na ono \u0161to zapravo \u017eelite imati. Ako se odbace te alokacije, mo\u017ee se posti\u0107i petostruko ubrzanje. <\/p>\n<p><\/p>\n<p>I to nije ne\u0161to \u0161to je posebno te\u0161ko. Ako pogledate kod iz pravog ugla, sve postaje prili\u010dno jednostavno, \u010dim shvatite su\u0161tinu problema. Ne treba prestati s alokacijom memorije: problem je u tome \u0161to ne\u0161to alocirate, a ono odmah umire, pri \u010demu sagorijeva va\u017ean resurs, a to je u ovom slu\u010daju propusnost memorije. Sve to rezultira padom performansi. Na x86 obi\u010dno je potrebno aktivno tro\u0161iti takte procesora, dok ste ovdje sagorjeli svu memoriju mnogo ranije. Rje\u0161enje je smanjiti broj alokacija.\u00a0<br \/>\nDrugi deo problema je u tome \u0161to, kada pokrenete profajler, kada se ispuni memorijska linija, u trenutku kada se to doga\u0111a, obi\u010dno \u010dekate povratak ke\u0161a, jer je pun sme\u0107a koje ste upravo stvorili, svim tim redovima. Stoga svaka operacija u\u010ditavanja ili spremanja postaje spora, jer dovodi do proma\u0161aja u ke\u0161u \u2013 ceo ke\u0161 postaje spor, \u010dekaju\u0107i da sme\u0107e nestane. Zato profajler obi\u010dno samo pokazuje topli slu\u010dajni \u0161um, razvu\u010den du\u017e celog ciklusa \u2013 ne\u0107e biti nikakve posebno vru\u0107e instrukcije ili mesta u kodu. Samo \u0161um. I ako pogledate GC petlje, sve \u0107e biti iz Young Generation i super brze \u2013 mikrosekunde ili milisekunde maksimalno. Jer cela ta memorija umire trenutno. Alocirate milijarde gigabajta, i on ih se\u010de, i se\u010de, i ponovo se\u010de. Sve se to doga\u0111a vrlo brzo. Dakle, imamo jeftine GC petlje, topli \u0161um du\u017e celog ciklusa, ali \u017eelimo dobiti petostruko ubrzanje. U tom trenutku ne\u0161to u glavi treba da se zatvori i zazvoni: \u201eza\u0161to je to tako?!\u201c. Preoptere\u0107enje memorijske linije ne prikazuje se u klasi\u010dnom debageru, potrebno je pokrenuti debager hardverskih broja\u010da performansi i videti to sami i direktno. A indirektno se to mo\u017ee posumnjati iz ova tri simptoma. Tre\u0107i simptom je kada gledate \u0161ta alocirate, pitate profajlera, a on odgovara: \u201eNapravio si milijardu redova, ali GC je radio besplatno\u201c. Kada se to desi, shvatite da ste stvorili previ\u0161e objekata i sagoreli celu memorijsku liniju. Postoji na\u010din da se to razjasni, ali nije o\u010digledan.\u00a0<\/p>\n<p><\/p>\n<p>Problem u strukturi podataka: gole strukture koje le\u017ee iza svega \u0161to se doga\u0111a, prevelike su, zauzimaju 2.7G na disku, pa je izuzetno nepo\u017eeljno praviti kopiju ovog sistema \u2013 \u017eelimo ga u\u010ditati iz mre\u017enog bajtnog bafera odmah u registre, kako ne bismo \u010ditali i pisali u red bezbroj puta. Na\u017ealost, Java prema zadanim postavkama ne nudi takvu biblioteku unutar JDK-a. Ali to je trivijalno, zar ne? U osnovi, to su 5-10 redaka koda potrebnih za implementaciju vlastitog baferiranog u\u010dita\u010da linija, koji opona\u0161a pona\u0161anje klase String, dok je zapravo omota\u010d oko donjeg bajtnog bafera. Kao rezultat, radi\u0161 gotovo kao da radi\u0161 sa stringovima, ali u stvarnosti se pomi\u010du pokaziva\u010di na bafer, a sirovi bajtovi se nigdje ne kopiraju, \u010dime se ponovo koriste isti baferi, iznova i iznova, a operacijski sustav je sretan da preuzme stvari za koje je namijenjen, poput skrivene dvostruke baferizacije tih bajtnih bafera, dok vi\u0161e ne mlati\u0161 beskrajan tok nepotrebnih podataka. Usput, shva\u0107ate li, pri radu s GC-om, da je zajam\u010deno da svaka alokacija memorije ne\u0107e biti vidljiva procesoru nakon posljednjeg ciklusa GC-a? Stoga, ni\u0161ta od ovoga ne mo\u017ee biti u cache-u, i desi se 100%-tno zajam\u010den proma\u0161aj. Pri radu s pokaziva\u010dem, na x86 \u010ditanje registra iz memorije traje 1-2 ciklusa, i \u010dim se to dogodi, pla\u0107a\u0161, pla\u0107a\u0161, pla\u0107a\u0161, jer je cijela memorija na <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Cache_inclusion_policy\">NINE cache-ima<\/a><\/noindex> \u2013 i to je pravi tro\u0161ak alokacije memorije. Pravi tro\u0161ak.<\/p>\n<p><\/p>\n<p>Drugim rije\u010dima, strukture podataka su ono \u0161to se najte\u017ee mijenja. I \u010dim shvatite da ste odabrali pogre\u0161nu strukturu podataka koja \u0107e kasnije uni\u0161titi performanse, obi\u010dno je potrebno ulo\u017eiti zna\u010dajan trud, no ako to ne u\u010dinite, stvari \u0107e postati jo\u0161 gore. Prije svega, treba razmi\u0161ljati o strukturama podataka, to je va\u017eno. Glavni tro\u0161ak dolazi od masivnih struktura podataka koje po\u010dinjemo koristiti na na\u010din 'kopirao sam strukturu podataka X u strukturu podataka Y, jer mi se Y vi\u0161e svi\u0111a vizualno.' No operacija kopiranja (koja se \u010dini jeftinom) zapravo tro\u0161i memorijsku propusnost i to je mjesto gdje se skriva sve izgubljeno vrijeme izvo\u0111enja. Ako imam ogromnu JSON string i \u017eelim je pretvoriti u strukturirano DOM stablo iz POJO ili ne\u010dega sli\u010dnog, operacija parsiranja te string i izgradnje POJO, a zatim novo pozivanje POJO kasnije pretvorit \u0107e se u dodatne tro\u0161kove - to nije jeftino. Osim ako ne planirate koristiti POJO mnogo \u010de\u0161\u0107e nego string. U prvo vrijeme, umjesto toga, mo\u017eete poku\u0161ati de\u0161ifrirati string i izvu\u0107i iz njega samo ono \u0161to vam treba, ne pretvaraju\u0107i ga u POJO. Ako se sve to doga\u0111a na putu gdje su potrebne maksimalne performanse, zaboravite na POJO - trebate se direktno baviti stringom.<\/p>\n<p><\/p>\n<h1 id=\"zachem-sozdavat-svoy-yazyk-programmirovaniya\">Why create your own programming language<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Rekli ste da za razumijevanje modela tro\u0161kova, trebate napisati svoj mali jezik\u2026<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Ne jezik, ve\u0107 kompajler. Jezik i kompajler su razli\u010dite stvari. Najve\u0107a razlika je u va\u0161oj glavi.\u00a0<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Usput, koliko znam, eksperimentirate s kreiranjem vlastitih jezika. Za\u0161to?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Zato \u0161to mogu! Polu sam u penziji, tako da je ovo moj hobi. Celu sam \u017eivot realizovao tu\u0111e jezike. Tako\u0111e sam puno radio na stilu kodiranja. A i zato \u0161to vidim probleme u drugim jezicima. Vidim da postoje bolje na\u010dine da radite uobi\u010dajene stvari. I \u017eeleo bih ih iskoristiti. Samo sam se umorio od gledanja problema u sebi, u Javi, u Pythonu, u bilo kom drugom jeziku. Trenutno pi\u0161em na React Native, JavaScript i Elm kao hobi koji nije o penziji, ve\u0107 o aktivnom radu. I pi\u0161em i na Pythonu, i verovatno \u0107u nastaviti da radim na ma\u0161inskom u\u010denju za Java backendove. Postoji mnogo popularnih jezika i svi imaju zanimljive osobine. Svaki je dobar na svoj na\u010din i mo\u017eete poku\u0161ati da spojite sve te karakteristike. Tako da se bavim istra\u017eivanjem zanimljivih stvari za mene, pona\u0161anjem jezika, poku\u0161avam da smi\u0161ljam razumnu semantiku. I za sada ide! Trenutno se borim sa semantikom memorije, jer \u017eelim da je imam kao u C i Javi, i da dobijem sna\u017ean model memorije i semantiku za u\u010ditavanja i skladi\u0161tenja. U isto vreme da imam automatsko odre\u0111ivanje tipova kao u Haskelu. Tako da poku\u0161avam da pome\u0161am Haskell-sli\u010dnu automatsku dedukciju tipova sa memorijom koja funkcioni\u0161e kao u C i Javi. Time sam se bavio poslednja 2-3 meseca, na primer.<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Ako gradite jezik koji uzima najbolje aspekte iz drugih jezika, da li ste razmi\u0161ljali da bi neko mogao da uradi obrnuto: uzme va\u0161e ideje i koristi ih kod sebe?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Upravo tako se pojavljuju novi jezici! Za\u0161to je Java sli\u010dna C-u? Zato \u0161to je C imao dobru sintaksu koju su svi razumeli, a Java se inspirisala tom sintaksom, dodav\u0161i bezbednost tipova, provere granica nizova, GC, a tako\u0111e su pobolj\u0161ali neke stvari iz C-a. Dodali su svoje. Ali su se prili\u010dno sna\u017eno inspirisali, zar ne? Svi stojimo na ple\u0107ima divova koji su bili pre nas \u2013 tako se ostvaruje napredak.<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Kako razumem, va\u0161 jezik \u0107e biti bezbedan kada je u pitanju kori\u0161\u0107enje memorije. Da li ste razmi\u0161ljali o implementaciji ne\u010dega poput borrow checkera iz Rusta? Da li ste ga gledali, kako vam se dopada?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Pa, pi\u0161em u C-u ve\u0107 cijelu vje\u010dnost, s tim svim malloc i free, i ru\u010dno upravljam vremenom \u017eivota. Znate, 90-95% ru\u010dno upravljanog \u017eivotnog ciklusa ima istu strukturu. I jako, jako je bolno baviti se tim ru\u010dno. Volio bih da kompajler jednostavno ka\u017ee \u0161to se doga\u0111a i \u0161to ste postigli sa svojim radnjama. Za neke stvari, borrow checker to radi automatski. Tako\u0111er bi trebao automatski pru\u017eati informacije, sve razumjeti i \u010dak me ne optere\u0107ivati time da to razumijevanje izlo\u017eim. Trebao bi raditi barem lokalnu analizu eskapiranja, i samo ako to ne uspije, tada bi trebalo dodavati anotacije tipova koje \u0107e opisivati \u017eivotni ciklus \u2013 a takav sustav je daleko slo\u017eeniji od borrow checkera, ili uop\u0107e bilo kojeg postoje\u0107eg provjerava\u010da memorije. Izbor izme\u0111u \u201esve je u redu\u201c i \u201enisam ni\u0161ta razumio\u201c \u2014 ne, trebao bi postojati ne\u0161to bolje.\u00a0<br \/>\nKao netko tko je napisao puno koda na C-u, vjerujem da je podr\u0161ka za automatsko upravljanje vremenom trajanja (lifetime) najva\u017enija stvar. Tako\u0111er, umoran sam od ogromne potro\u0161nje memorije u Javi, a glavni problem je u GC-u. Kada alocira\u0161 memoriju u Javi, ne vra\u0107a\u0161 memoriju koja je bila lokalna u posljednjem ciklusu GC-a. U jezicima s to\u010dnijim upravljanjem memorijom to nije slu\u010daj. Ako pozove\u0161 malloc, odmah dobija\u0161 memoriju koja je obi\u010dno upravo kori\u0161tena. Obi\u010dno radi\u0161 neke privremene stvari s memorijom i odmah je vra\u0107a\u0161. I ona se odmah vra\u0107a u malloc pool, a sljede\u0107i malloc ciklus ponovno je izvla\u010di. Dakle, stvarna upotreba memorije smanjuje se na skup aktivnih objekata u odre\u0111enom trenutku, plus curenja. Ako ti ne curi sve na posve neprimjeren na\u010din, ve\u0107ina memorije zavr\u0161i u cache-evima i procesoru, i to radi brzo. No, zahtijeva puno ru\u010dnog upravljanja memorijom putem malloc i free, pozvanih u pravom redu, na pravom mjestu. Rust mo\u017ee sam ispravno upravljati s tim, a u mnogim slu\u010dajevima dati \u010dak i bolju izvedbu, jer se potro\u0161nja memorije su\u017eava samo na trenutne izra\u010dune \u2013 nasuprot \u010dekanju sljede\u0107eg GC ciklusa koji \u0107e osloboditi memoriju. Na kraju, dobili smo vrlo zanimljiv na\u010din za pobolj\u0161anje izvedbe. I prili\u010dno mo\u0107an \u2013 mislim, bavio sam se takvim stvarima prilikom obrade podataka za finteh, i to je omogu\u0107ilo ubrzanje od otprilike pet puta. To je prili\u010dno veliko ubrzanje, posebno u svijetu gdje procesori ne postaju br\u017ei, a mi i dalje \u010dekamo pobolj\u0161anja.<\/p>\n<p><\/p>\n<h1 id=\"karera-performans-inzhenera\">Career of a performance engineer<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Tako\u0111er bih \u017eelio malo pitati o karijeri u cjelini. Postali ste poznati zahvaljuju\u0107i radu na JIT-u u HotSpot-u, a zatim ste pre\u0161li u Azul \u2013 koji je tako\u0111er JVM tvrtka. No, vi\u0161e ste se bavili hardverom nego softverom. I onda ste iznenada pre\u0161li na Big Data i Machine Learning, a potom na otkrivanje prijevara. Kako se to dogodilo? To su vrlo razli\u010dita podru\u010dja razvoja.<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Dugo se bavim programiranjem i imao sam prilike raditi na raznim projektima. Kada ljudi ka\u017eu: \u201eOh, ti si onaj koji je radio JIT za Java!\u201d, uvijek mi je smije\u0161no. Prije toga bavim se klonom PostScript-a \u2013 jezika koji je Apple nekada koristio za svoje laserske pisa\u010de. A prije toga sam implementirao jezik Forth. Mislim da je zajedni\u010dka tema za mene \u2013 razvoj alata. Cijeli \u017eivot radim alate pomo\u0107u kojih drugi ljudi pi\u0161u svoje fantasti\u010dne programe. Tako\u0111er sam se bavio razvojem operativnih sustava, drajvera na razini jezgre, jezika za razvoj OS-a, koji su zapo\u010deli trivijalno, ali su s vremenom postajali sve slo\u017eeniji. No, osnovna tema ostaje \u2013 razvoj alata. Velik dio mog \u017eivota pro\u0161ao je izme\u0111u Azula i Suna, i taj dio bio je vezan uz Java. Kada sam se upustio u Big Data i Strojno U\u010denje, ponovno sam stavio svoj elegantni \u0161e\u0161ir i rekao: \u201eOh, sada imamo netrivijalni problem, a ovdje se doga\u0111a mnogo zanimljivih stvari i ljudi koji ne\u0161to rade\u201d. To je odli\u010dan put za razvoj kroz koji vrijedi pro\u0107i. <\/p>\n<p><\/p>\n<p>Da, vrlo volim distribuirano ra\u010dunarstvo. Moj prvi posao bio je tijekom studija na C-u, na reklamnom projektu. To je bilo distribuirano ra\u010dunarstvo na Zilog Z80 \u010dipovima, koji su prikupljali podatke za analogno opti\u010dko prepoznavanje teksta, koje je provodio pravi analogni analizator. Bila je to nevjerojatna i potpuno neobi\u010dna tema. No, bilo je pote\u0161ko\u0107a, neki dijelovi nisu se ispravno prepoznavali, pa je bilo potrebno izvu\u0107i sliku i pokazati je osobi koja je ve\u0107 pro\u010ditala o\u010dima i javila \u0161to se tamo nalazi, i zbog toga su postojali poslovi s podacima, a ti su poslovi imali svoj vlastiti jezik. Postojala je pozadina koja je sve to obra\u0111ivala - paralelno radili su Z80 s pokrenutim vt100 terminalima - jedan za svaku osobu, a bila je i paralelna programska paradigma na Z80. Postojao je neki zajedni\u010dki komad memorije koji su dijelili svi Z80 unutar konfiguracije tipa 'zvijezda'; dijelili su se i backplane, a polovica RAM-a dijelila se unutar mre\u017ee, dok je druga polovica bila privatna ili odlazila na ne\u0161to drugo. Smisleno slo\u017een paralelni distribuirani sustav s dijeljenom... polu-dijeljenom memorijom. Kada se to dogodilo... Ve\u0107 ni ne pamtim, negdje sredinom 80-ih. Prili\u010dno davno.\u00a0<br \/>\nDa, mo\u017eemo smatrati da je 30 godina dovoljno dugo. Zadatci povezani s distribuiranim ra\u010dunarstvom postoje ve\u0107 dovoljno dugo, ljudi su odavno ratovali s <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/Beowulf_(%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80)\">Beowulf<\/a><\/noindex>-klasterima. Takvi klasteri izgledaju kao\u2026 Na primjer: postoji Ethernet i va\u0161 brzi x86 je povezan na taj Ethernet, i sada \u017eelite dobiti la\u017enu dijeljenu memoriju, jer nitko tada nije mogao raditi na kodiranju distribuiranih izra\u010duna, to je bilo prekomplicirano, i zato je postojala la\u017ena dijeljena memorija sa za\u0161titom stranica memorije na x86, i ako ste pisali u tu stranicu, govorili smo ostalim procesorima da ako dobiju pristup istoj dijeljenoj memoriji, trebaju je u\u010ditati od vas, i tako se pojavila neka vrsta protokola podr\u0161ke za koherentnost predmemorija i softvera za to. Zanimljiva koncept. Pravi problem, naravno, bio je u ne\u010demu drugom. Sve je to radilo, ali ste brzo po\u010deli dobivati probleme s performansama, jer nitko nije razumio model performansi na dovoljno dobrom nivou \u2013 koji su obrasci pristupa memoriji, kako u\u010diniti da \u010dvorovi beskona\u010dno ne pingaju jedni druge, i tako dalje. <\/p>\n<p><\/p>\n<p>U H2O sam smislio ovo: sami developeri su odgovorni za to da odrede gde postoji paralelizam, a gde ne. Stvorio sam model kodiranja koji \u010dini pisanje visokoperformantnog koda jednostavnim. Me\u0111utim, napisati spor kod je ote\u017eano; izgledat \u0107e lo\u0161e. Potrebno je dosta truda da se napi\u0161e spor kod, koristi\u0107e se nekonvencionalne metode. Sporan kod mo\u017ee se uo\u010diti ve\u0107 na prvi pogled. Kao posledica, obi\u010dno se pi\u0161e kod koji radi brzo, ali morate se nositi s pitanjem kako upravljati deljenom memorijom. Sve se to vrti oko velikih nizova, a pona\u0161anje je sli\u010dno nevolatilnim velikim nizovima u paralelnoj Javi. Zamislite da dva niti pi\u0161u u paralelni niz, jedan od njih dobija, a drugi gubi, i ne znate ko je ko. Ako nisu volatilni, redosled mo\u017ee biti bilo kakav - i to zaista dobro funkcioni\u0161e. Ljudi se zaista brinu o redosledu operacija, pravilno postavljaju volatile i o\u010dekuju probleme s performansama povezane s memorijom na pravim mestima. U suprotnom, jednostavno bi pisali kod u obliku petlji od 1 do N, gde je N neki trilijun, nadaju\u0107i se da \u0107e svi slo\u017eeni slu\u010dajevi automatski postati paralelni - a to tamo ne funkcioni\u0161e. Ali u H2O to nije ni Java ni Scala, mo\u017ee se smatrati 'Java minus minus', ako \u017eelite. To je veoma razumljiv stil programiranja i podse\u0107a na pisanje jednostavnog koda u C ili Javi sa petljama i nizovima. Ali pri tome se memorija mo\u017ee obra\u0111ivati terabajtima. I dalje koristim H2O. Povremeno ga koristim u razli\u010ditim projektima - i to je i dalje najbr\u017ea stvar, deset puta br\u017ea od konkurenata. Ako radite s velikim podacima u kolumnarnim formatima, vrlo je te\u0161ko nadma\u0161iti H2O.<\/p>\n<p><\/p>\n<h1 id=\"tehnicheskie-chellenzhi\">Technical challenges<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Koji je bio va\u0161 najve\u0107i izazov tokom karijere?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Da li razgovaramo o tehni\u010dkom ili ne tehni\u010dkom delu pitanja? Rekao bih da su najve\u0107i izazovi - ne tehni\u010dki.\u00a0<br \/>\n\u0160to se ti\u010de tehni\u010dkih izazova. Jednostavno sam ih prevladao. \u010cak ni ne znam koji je bio najve\u0107i, ali bilo je nekoliko prili\u010dno zanimljivih, koje su zauzele dosta vremena i mentalne borbe. Kada sam oti\u0161ao u Sun, bio sam siguran da \u0107u napraviti brzi kompajler, dok su mnogi seniori govorili da mi nikada ne\u0107e uspjeti. Ali krenuo sam tim putem, napisao kompajler do alokatora registara, i bio je prili\u010dno brz. Bio je jednako brz kao moderni C1, ali tada je alokator bio mnogo sporiji, a gledaju\u0107i unatrag \u2013 to je bio problem velike strukture podataka. Trebala mi je da napi\u0161em grafi\u010dki alokator registara i nisam razumio dilemu izme\u0111u izra\u017eajnosti koda i brzine, koja je postojala u to doba i bila vrlo va\u017ena. Ispostavilo se da struktura podataka obi\u010dno prema\u0161uje veli\u010dinu ke\u0161a na x86 tada\u0161njeg vremena i stoga, ako sam prvotno pretpostavio da \u0107e alokator registara odraditi 5-10 posto cijelog vremena JIT-ovanja, u stvarnosti je to prerastalo u 50 posto. <\/p>\n<p><\/p>\n<p>Vrijeme je prolazilo, kompajler je postajao sve jasniji i u\u010dinkovitiji, prestao je generirati odvratan kod u ve\u0107em broju slu\u010dajeva, i performanse su sve vi\u0161e po\u010dele li\u010diti na ono \u0161to daje C kompajler. Ako, naravno, ne pi\u0161e\u0161 neku glupost koju \u010dak ni C ne mo\u017ee ubrzati. Ako pi\u0161e\u0161 kod kao u C-u, dobiva\u0161 performanse poput C-a u ve\u0107em broju slu\u010dajeva. I \u0161to je dalje i\u0161lo, kod je sve vi\u0161e asimptotski odgovarao razini C, alokator registara je po\u010deo li\u010diti na ne\u0161to zavr\u0161eno\u2026 bez obzira na to radi li tvoj kod brzo ili sporo. Nastavio sam raditi na alokatoru, kako bi obavljao bolje alokacije. Postajao je sve sporiji, ali je davavao sve bolje performanse u slu\u010dajevima kada nitko nije mogao uspjeti. Mogao sam zaroniti u alokator registara, potro\u0161iti mjesec rada, i odjednom bi sav kod po\u010deo raditi 5% br\u017ee. To se doga\u0111alo iznova i iznova i alokator registara postao je ne\u0161to poput umjetni\u010dkog djela \u2013 svi su ga voleli ili mrzeli, a ljudi iz akademske zajednice postavljali su pitanja o tome \"za\u0161to se sve radi upravo ovako\", za\u0161to ne <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Register_allocation#Linear_Scan\">linearna skeniranja<\/a><\/noindex>, i koja je razlika. Odgovor je uvijek isti: alokator temeljen na boji grafa plus vrlo pa\u017eljivo upravljanje predmemoriranim kodom jednako je oru\u017eje pobjede, najbolja kombinacija koju nitko ne mo\u017ee nadma\u0161iti. I to je prili\u010dno nevidljiva stvar. Sve ostalo \u0161to compiler radi - to su prili\u010dno prou\u010dene stvari, iako su tako\u0111er dovedene do razine umjetnosti. Uvijek sam radio stvari koje su trebale pretvoriti compiler u umjetni\u010dko djelo. No, ni\u0161ta od toga nije bilo izvanredno - osim alokatora registara. Caka je u tome \u0161to treba pa\u017eljivo <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Register_allocation\">odrezati<\/a><\/noindex> pod optere\u0107enjem i, ako se to dogodi ( mogu detaljnije objasniti ako je to zanimljivo), to zna\u010di da se mo\u017ee agresivnije inline-ati, bez rizika od prekora\u010denja zakrivljenosti grafikon performansi. U to vrijeme bilo je gomila sveobuhvatnih compilera, prepunih dodataka i zvu\u010dnih efekata, koji su imali alokatore registara, ali nitko to vi\u0161e nije mogao. <\/p>\n<p><\/p>\n<p>Problem je u tome \u0161to, ako dodaje\u0161 metode koje podlije\u017eu inliningu, pove\u0107avaju\u0107i i pove\u0107avaju\u0107i podru\u010dje inlininga, skup kori\u0161tenih vrijednosti odmah nadma\u0161uje broj registara, \u0161to dovodi do spillanja. Kriti\u010dna razina obi\u010dno nastaje kada alokator popusti, a jedan dobar kandidat za spillanje vrijedi vi\u0161e od drugoga, pa spillas neke zaista divlje stvari. Vrijednost inlininga ovdje je u tome \u0161to gubi\u0161 dio overheada, overheada na poziv i o\u010duvanje, mo\u017ee\u0161 vidjeti vrijednosti iznutra i mo\u017ee\u0161 ih dalje optimizirati. Tro\u0161ak inlininga je u tome \u0161to se stvara veliki broj \u017eivih vrijednosti, i ako tvoj alokator registara spili vi\u0161e nego \u0161to je potrebno, odmah gubi\u0161. Zato, ve\u0107ina alokatora ima problem: kada inlining prelazi neku granicu, po\u010dinju se spillati svi na svijetu i performanse mogu oti\u0107i niz odvod. Oni koji implementiraju kompajler dodaju neke heuristike: na primjer, da zaustave inlining kada dostigne neku dovoljnu veli\u010dinu, jer \u0107e alokacije sve pokvariti. Tako se formira slom grafika performansi \u2013 inlinira\u0161, inlinira\u0161, performanse polako rastu \u2013 a onda bum! \u2013 pada naglo, jer si preinlinirao previ\u0161e. Tako je sve funkcioniralo prije pojave Jave. Java zahtijeva mnogo vi\u0161e inlininga, pa sam morao u\u010diniti svoj alokator mnogo agresivnijim, kako bi se izjedna\u010dio, a ne sru\u0161io, i ako si previ\u0161e inlinirao \u2013 po\u010dinje spillati, ali onda opet dolazi trenutak \u201enema vi\u0161e spillanja\u201c. To je zanimljivo zapa\u017eanje i do\u0161lo mi je jednostavno iz ni\u010dega, ne evidentno, ali se dobro isplatilo. Zapo\u010deo sam s agresivnim inliningom i to me odvelo na mjesta gdje se performanse Jave i C-a nalaze jedne pored drugih. Stvarno su blizu \u2013 mogu pisati kod na Javi koji \u0107e biti znatno br\u017ei od C koda i sli\u010dno, ali u prosjeku, u velikoj slici stvari, oni su otprilike usporedivi. \u010cini mi se da je dio ove zasluge \u2013 alokator registara, koji mi omogu\u0107uje da inliniram maksimalno jednostavno. Jednostavno inliniram sve \u0161to vidim. Pitanje je ovdje radi li alokator dobro, proizlazi li kao rezultat razuman radni kod. Ovo je bio veliki izazov: razumjeti sve to i natjerati ga da radi.<\/p>\n<p><\/p>\n<h1 id=\"nemnogo-pro-allokaciyu-registrov-i-mnogoyadernost\">A bit about register allocation and multithreading<\/h1>\n<p><\/p>\n<p><strong>Vladimir<\/strong>: Problemi poput alokacije registara \u010dine se kao neka vje\u010dna, beskona\u010dna tema. Zanimljivo je, je li neka ideja izgledala obe\u0107avaju\u0107e, a onda zakazala u praksi?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Naravno! Alokacija registara je podru\u010dje u kojem za rje\u0161avanje NP-potpunog problema poku\u0161ava\u0161 prona\u0107i neke heuristike. I nikada ne mo\u017ee\u0161 posti\u0107i idealno rje\u0161enje, zar ne? To je jednostavno nemogu\u0107e. Pogledajte, Ahead of Time kompilacija \u2013 ona tako\u0111er lo\u0161e radi. O \u010demu se ovdje radi? O nekim prosje\u010dnim slu\u010dajevima. O tipi\u010dnoj izvedbi, tako da mo\u017ee\u0161 oti\u0107i i izmjeriti ne\u0161to za \u0161to smatra\u0161 da je dobra tipi\u010dna izvedba \u2013 na kraju krajeva, ti doista radi\u0161 na njenom pobolj\u0161anju! Alokacija registara je tema posve\u0107ena izvedbi. \u010cim ima\u0161 prvi prototip, radi i oboja \u0161to treba, zapo\u010dinje rad na performansama. Treba\u0161 nau\u010diti dobro mjeriti. Za\u0161to je to va\u017eno? Ako postoje jasni podaci, mo\u017ee\u0161 gledati na razli\u010ditim dijelovima i vidjeti: aha, ovo je pomoglo ovdje, ali ovdje je sve propalo! Pojavljuju se neke dobre ideje, dodaje\u0161 novu heuristiku i odjednom sve po\u010dinje raditi prosje\u010dno malo bolje. Ili ne po\u010dinje. Imao sam puno slu\u010dajeva kada smo se borili za pet posto izvedbe koja je razlikovala na\u0161 razvoj od prethodnog alokatora. I svaki put to izgleda ovako: negdje si pobijedio, negdje si izgubio. Ako ima\u0161 dobre alate za analizu performansi, mo\u017ee\u0161 prona\u0107i gubitni\u010dke ideje i shvatiti za\u0161to gube. Mo\u017eda bi bilo bolje ostaviti sve kako je, a mo\u017eda se ozbiljnije posvetiti finom pode\u0161avanju, ili oti\u0107i i popraviti ne\u0161to drugo. To je cijeli set stvari! Napravio sam ovaj cool hax, ali treba i ovaj, i ovaj, i ovaj \u2013 i njihova ukupna kombinacija daje neka pobolj\u0161anja. A pojedinci mogu propasti. Takva je priroda rada na performansama NP-potpunih zadataka.<\/p>\n<p><\/p>\n<p><strong>Vladimir<\/strong>: \u010cini se da su stvari poput obojanja u alokatorima ve\u0107 rije\u0161ene. Pa, za vas su rije\u0161ene, sude\u0107i prema tome \u0161to pri\u010date, pa vrijedi li uop\u0107e...<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Nije re\u0161ena sama po sebi. Ti je mora\u0161 pretvoriti u 're\u0161enu'. Postoje te\u0161ki zadaci koje treba re\u0161iti. Kada to uradi\u0161, dolazi vreme za rad na performansama. Na taj posao treba pristupiti odgovaraju\u0107e - raditi benchmarking, prikupljati metrike, obja\u0161njavati situacije kada je, vra\u0107anjem na prethodnu verziju, tvoja stara metoda ponovo po\u010dela da radi (ili obrnuto, prestala). I ne odustaj dok ne\u0161to ne postigne\u0161. Kao \u0161to sam ve\u0107 rekao, ako su sjajne ideje koje nisu uspele, u oblasti alokacije registara ideja je otprilike beskona\u010dna. Mo\u017ee\u0161, na primer, \u010ditati nau\u010dne publikacije. Iako je ova oblast sada postala pomerena mnogo sporije i jasnija nego u vreme svoje mladosti. Ipak, u ovoj oblasti radi cela beskona\u010dnost ljudi i sve njihove ideje vredi isprobati, svi \u010dekaju svoj trenutak. I ne mo\u017ee\u0161 re\u0107i koliko su dobre ako ih ne isproba\u0161. Koliko dobro se integri\u0161u sa svime ostalim u tvojoj alokaciji, jer alokacija radi mnoge stvari, i neke ideje u tvojoj konkretnoj alokaciji mo\u017eda ne\u0107e raditi, a u drugoj alokaciji - lako. Glavni na\u010din pobede za alokaciju je izbaciti sporu stvar van glavne staze i prisiliti je da se deli du\u017e granica sporih puteva. Zato, ako \u017eeli\u0161 da pokrene\u0161 GC, kreni sporim putem, deoptimizuj, izbaci izuzetak, sve u tom stilu - zna\u0161 da su te stvari relativno retke. I zaista su retke, proverio sam. Radi\u0161 dodatni posao i zahvaljuju\u0107i tome nestaje mnogo ograni\u010denja na tim sporim putevima, ali to nije toliko va\u017eno, jer su spori i retko se prolazi preko njih. Na primer, nulti pokaziva\u010d - nikada se ne de\u0161ava, zar ne? Treba imati nekoliko puteva za razli\u010dite stvari, ali oni se ne smeju me\u0161ati na glavnom.\u00a0<\/p>\n<p><\/p>\n<p><strong>Vladimir<\/strong>: \u0160ta misli\u0161 o mnogoj jezgri, kada ih ima hiljade odjednom? Da li je to korisna stvar?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Uspeh GPU pokazuje da je prili\u010dno koristan!<\/p>\n<p><\/p>\n<p><strong>Vladimir<\/strong>: Oni su prili\u010dno specijalizovani. A \u0161ta je sa procesorima op\u0161te namene?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Pa, to je bio poslovni model Azula. Odgovor je do\u0161ao jo\u0161 u eri kada su ljudi jako voljeli predvidivu performansu. Tada je bilo te\u0161ko pisati paralelni kod. H2O model kodiranja se dobro skalira, ali nije model op\u0107e namjene. Osim ako nije malo op\u0107enitiji u usporedbi s kori\u0161tenjem GPU-a. Govorimo li o slo\u017eenosti razvoja ne\u010dega takvog ili o slo\u017eenosti njegove upotrebe? Na primjer, zanimljiva lekcija koju mi je dao Azul, prili\u010dno ne o\u010digledna: mali ke\u0161evi su u redu.\u00a0<\/p>\n<p><\/p>\n<h1 id=\"samyy-bolshoy-chellenzh-v-zhizni\">The biggest challenge in life<\/h1>\n<p><\/p>\n<p><strong>Vladimir<\/strong>: \u0160to je s netehni\u010dkim izazovima?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Najve\u0107i izazov bio je ne biti... ljubazan i dobar prema ljudima. Kao rezultat toga, stalno sam se na\u0161ao u ekstremno konfliktnim situacijama. Onima u kojima sam znao da sve ide naopako, ali nisam znao kako napredovati u rje\u0161avanju tih problema i nisam se znao nositi s njima. Mnoge dugotrajne probleme koji traju desetlje\u0107ima pojavili su se upravo na taj na\u010din. To \u0161to u Javi postoje C1 i C2 kompajleri \u2013 neposredna je posljedica toga. To \u0161to u Javi ve\u0107 deset godina nije bilo vi\u0161eslojne kompilacije \u2013 tako\u0111er je neposredna posljedica. O\u010digledno nam je bio potreban takav sustav, ali nije o\u010digledno za\u0161to ga nije bilo. Imao sam problema s jednim in\u017eenjerom... ili grupom in\u017eenjera. Davno, kada sam po\u010deo raditi u Sunu, bio sam... dobro, ne samo tada, ja zapravo uvijek imam svoje mi\u0161ljenje o svemu. I smatrao sam istinitim da se jednostavno mo\u017ee uzeti ta vlastita istina i re\u0107i je bez uvijanja. Tim vi\u0161e \u0161to sam ve\u0107inu vremena bio \u0161okantno u pravu. I ako ti se takav pristup ne svi\u0111a... pogotovo ako o\u010digledno grije\u0161i\u0161 i radi\u0161 gluposti... Uglavnom, malo ljudi moglo je podnijeti takav oblik komunikacije. Ipak, neki su mogli, na primjer, ja. Cijeli sam \u017eivot gradio na meritokratskim principima. Ako mi poka\u017eete ne\u0161to \u0161to nije u redu, odmah \u0107u se okrenuti i re\u0107i: rekao si glupost. Pri tome se, naravno, izvinjavam i sve to, isti\u010dem zasluge, ako ih uop\u0107e ima, i \u010dinim druge ispravne korake. S druge strane, ja sam \u0161okantno u pravu \u0161okantno veliki postotak ukupnog vremena. I to ne funkcionira ba\u0161 najbolje u odnosima s ljudima. I ne trudim se biti ljubazan, ve\u0107 postavljam pitanje direktno. 'To nikada ne\u0107e uspjeti, jer broj jedan, dva i tri.' A oni su tako: 'Oh!'. Bilo je i drugih posljedica koje je bolje propustiti: na primjer, one koje su dovele do razvoda s \u017eenom i deset godina depresije nakon toga.<\/p>\n<p><\/p>\n<p>Izazov je borba s ljudima, s njihovim percepcijama onoga \u0161to mo\u017ee\u0161 ili ne mo\u017ee\u0161 raditi, \u0161to je va\u017eno, a \u0161to nije. Bilo je mnogo izazova vezanih za stil kodiranja. Jo\u0161 uvijek pi\u0161em puno koda, a u to vrijeme morao sam se \u010dak usporiti jer sam radio previ\u0161e paralelnih zadataka i radili su ih slabo, umjesto da se usredoto\u010dim na jedan. Gledaju\u0107i unatrag, napisao sam polovicu koda tima Java JIT, tima C2. Sljede\u0107i najbr\u017ei programer pisao je dvostruko sporije, sljede\u0107i jo\u0161 duplo sporije i to je bio eksponencijalni pad. Sedmi u toj liniji bio je jako, jako spor \u2013 tako to uvijek ide! Dotaknuo sam se gomile koda. Gledao sam tko \u0161to pi\u0161e, bez iznimaka, buljio sam u njihov kod, pregledavao svakoga od njih, a i dalje sam pisao vi\u0161e od njih. Takav pristup s ljudima \u010desto ne funkcionira dobro. Neki to ne vole. A kada s tim ne mogu upravljati, po\u010dinju razne pritu\u017ebe. Na primjer, jednom su mi rekli da prestanem pisati kod jer pi\u0161em previ\u0161e i to ugro\u017eava tim, a meni je to sve zvu\u010dalo kao \u0161ala: \u010dovje\u010de, ako cijeli ostatak tima nestane, a ja nastavim pisati kod, ti \u0107e\u0161 izgubiti samo polovicu tima. S druge strane, ako nastavim pisati kod i ti izgubi\u0161 polovicu tima \u2013 to mi zvu\u010di kao jako lo\u0161e vo\u0111enje. Nikada posebno nisam razmi\u0161ljao o tome, nikada o tome nisam govorio, ali je svejedno bilo negdje u mojoj glavi. U dubini uma vrtjela se misao: 'Pa vi se svi \u0161alite'. Tako da, najve\u0107i problem sam bio ja i moje odnose s ljudima. Sada se bolje razumijem, dugo sam bio vo\u0111a tima programera, i sada ljudima izravno ka\u017eem: zna\u0161, ja sam onakvog kakav jesam i morat \u0107ete se nositi sa mnom \u2013 je li u redu da se tu postojim? I kada su se s tim po\u010deli nositi, sve je po\u010delo funkcionirati. Na kraju, nisam ni lo\u0161, ni dobar, nemam nikakve lo\u0161e namjere ili sebi\u010dne te\u017enje, to je samo moja priroda i s tim se nekako treba \u017eivjeti.<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Nedavno su svi po\u010deli govoriti o samosvijesti za introverte, i op\u0107enito o softver vje\u0161tinama. \u0160to se mo\u017ee re\u0107i o tome?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Da, to je bilo razumijevanje i lekcija koju sam izvukao iz razvoda s biv\u0161om \u017eenom. Ono \u0161to sam stekao iz razvoda \u2013 to je razumijevanje sebe. Tako sam po\u010deo razumjeti i druge ljude. Razumjeti kako ta interakcija funkcionira. To je dovelo do otkri\u0107a jedno za drugim. Pojavilo se svjesnost tko sam i \u0161to predstavljam. \u0160to radim: ili sam zaokupljen zadatkom, ili izbjegavam sukob, ili ne\u0161to drugo \u2013 i takva razina samosvijesti zaista poma\u017ee odr\u017eati se pod kontrolom. Nakon toga sve ide mnogo lak\u0161e. Jedna stvar koju sam otkrio ne samo kod sebe, ve\u0107 i kod drugih programera \u2013 nemogu\u0107nost verbaliziranja misli kada si pod emocionalnim stresom. Na primjer, sjedi\u0161, kodira\u0161, nalazite se u stanju toka, a onda ti tr\u010de i po\u010dinju vri\u0161tati u histeriji da je ne\u0161to pokvareno, i odmah \u0107e se primijeniti ekstremne mjere. I ne mo\u017ee\u0161 izgovoriti nijednu rije\u010d, jer si u stanju emocionalnog stresa. Ste\u010deno znanje omogu\u0107ava pripremu za taj trenutak, pro\u0107i kroz njega i pre\u0107i na plan povla\u010denja, nakon kojeg se mo\u017ee\u0161 tada ne\u0161to u\u010diniti. Dakle, da, kada po\u010dne\u0161 prepoznavati kako sve ovo funkcionira \u2013 to je ogroman doga\u0111aj koji mijenja \u017eivot.\u00a0<br \/>\nSam nisam mogao prona\u0107i prave rije\u010di, ali zapamtili ste niz postupaka. Bit je u tome da je ova reakcija \u2013 jednako fizi\u010dka koliko i verbalna, i treba ti prostor. Takav prostor, u zen smislu. To je ono \u0161to treba objasniti, a zatim odmah ustupiti \u2013 fizi\u010dki se udaljiti. Kada \u0161utim rije\u010dima, mogu obraditi situaciju u emotivnom smislu. Kako adrenalin dospije do mozga, prebacuje te u na\u010din rada \u2018udariti ili pobje\u0107i\u2019, vi\u0161e ne mo\u017ee\u0161 ni\u0161ta re\u0107i, ne \u2013 sada si idiot, in\u017eenjer za udaranje, nesposoban dati dostojan odgovor ili barem zaustaviti napad, a napada\u010d mo\u017ee slobodno ponovo i ponovo napadati. Prvo se mora\u0161 ponovno postati sebi, povratiti kontrolu, izi\u0107i iz re\u017eima \u2018udariti ili pobje\u0107i\u2019. <\/p>\n<p><\/p>\n<p>I za to je potrebno verbalno prostor. Samo slobodan prostor. Ako uop\u0107e ne\u0161to re\u0107i, to se mo\u017ee upravo tako izjaviti, a zatim oti\u0107i i stvarno prona\u0107i svoje \"prostor\": oti\u0107i u \u0161etnju po parku, zaklju\u010dati se u tu\u0161u - nije va\u017eno. Najva\u017enije je privremeno se isklju\u010diti iz te situacije. \u010cim se malo isklju\u010di\u0161, kontrola se vra\u0107a, po\u010dinje\u0161 razmi\u0161ljati jasno. \"Dobro, ja nisam neki idiot, ne radim glupe stvari, prili\u010dno sam korisna osoba.\" Kada uspije\u0161 uvjeriti samog sebe, vrijeme je za sljede\u0107u fazu: shvatiti \u0161to se dogodilo. Napali su te, napad je do\u0161ao odakle nisi ni o\u010dekivao, to je bila nepo\u0161tena, podla zamka. To je lo\u0161e. Sljede\u0107i korak je razumjeti za\u0161to je napada\u010du to bilo potrebno. Zaista, za\u0161to? Mo\u017eda zato \u0161to je sam u bijesu? Za\u0161to je u bijesu? Na primjer, zato \u0161to se sam osramotio i ne mo\u017ee preuzeti odgovornost? Na taj na\u010din treba pa\u017eljivo obraditi cijelu situaciju. No, za to je potrebno prostor za manevriranje, verbalno prostor. Prvi korak je prekinuti verbalni kontakt. Udaljiti se od rasprave rije\u010dima. Otka\u017ei to, udalji se \u0161to je br\u017ee mogu\u0107e. Ako je to telefonski razgovor - samo spusti slu\u0161alicu - to je vje\u0161tina koju sam stekao iz razgovora s biv\u0161om suprugom. Ako razgovor ne vodi ni\u010demu dobrom, jednostavno reci \"dovi\u0111enja\" i objesi slu\u0161alicu. S one strane slu\u0161alice: \"bla-bla-bla\", ti odgovara\u0161: \"aha, pa, \u010dao!\" i spusti\u0161 slu\u0161alicu. Jednostavno prekine\u0161 razgovor. Pet minuta kasnije, kada ti se vra\u0107a sposobnost racionalnog razmi\u0161ljanja, malo se ohladi\u0161, postaje mogu\u0107e razmisliti o tome \u0161to se uop\u0107e dogodilo i \u0161to \u0107e dalje biti. I po\u010deti formulirati promi\u0161ljeni odgovor, a ne samo reagirati na emocije. Za mene je proboj u samospoznaji upravo to \u0161to u slu\u010daju emocionalnog stresa ne mogu govoriti. Iza\u0107i iz tog stanja, razmisliti i isplanirati kako odgovoriti i kompenzirati probleme - to su pravi koraci kada ne mo\u017ee\u0161 govoriti. Najjednostavniji na\u010din je pobje\u0107i od situacije u kojoj se manifestira emocionalni stres i jednostavno prestati sudjelovati u tom stresu. Nakon toga dobiva\u0161 sposobnost razmi\u0161ljanja, kada mo\u017ee\u0161 razmi\u0161ljati, stvara\u0161 mogu\u0107nost govora i tako dalje.<\/p>\n<p><\/p>\n<p>Usput, u sudu advokat suprotne strane poku\u0161ava to u\u010diniti s tobom \u2013 sada je ve\u0107 jasno za\u0161to. Zato \u0161to ima mogu\u0107nost da te pritisne do takvog stanja da ne mo\u017ee\u0161 izgovoriti svoje ime, na primjer. U najdoslovnijem smislu, ne mo\u017ee\u0161 govoriti. Ako ti se to doga\u0111a i ako zna\u0161 da \u0107e\u0161 se na\u0107i na mjestu gdje se vode verbalne bitke, u mjestu poput suda, mo\u017ee\u0161 do\u0107i sa svojim pravnikom. Pravni stru\u010dnjak \u0107e se zauzeti za tebe i prekinuti verbalni napad, a to \u0107e u\u010diniti potpuno zakonitim putem, i tvoje izgubljeno zen mjesto \u0107e se vratiti. Na primjer, nekoliko puta sam morao nazvati obitelj, sudac je to smatrao prili\u010dno prijateljski, ali su advokat suprotne strane vikao i vi\u010dio na mene, nisam mogao ubaciti niti jednu rije\u010d. U takvim situacijama najbolje djeluje kori\u0161tenje posrednika. Posrednik prekida sav pritisak koji neprekidno te\u010de prema tebi, pronalazi\u0161 potrebno zen mjesto, zajedno s njim se vra\u0107a sposobnost govora. To je cijelo podru\u010dje znanja u kojem se mora mnogo u\u010diti, mnogo otkriti unutar sebe, a sve se to pretvara u visoko strate\u0161ke odluke, koje se razlikuju za razli\u010dite ljude. Neki ljudi nemaju gore opisane probleme, obi\u010dno ih nemaju ljudi koji se profesionalno bave prodajom. Svi ti ljudi koji zara\u0111uju za \u017eivot rije\u010dima \u2013 poznati pjeva\u010di, pjesnici, vjerski djelatnici i politi\u010dari, uvijek imaju \u0161to re\u0107i. Oni nemaju takvih problema, ali ja ih imam.<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: To je bilo\u2026 iznena\u0111uju\u0107e. Odli\u010dno, ve\u0107 smo razgovarali prili\u010dno dugo i vrijeme je za zavr\u0161etak ovog intervjua. Obavezno \u0107emo se sastati na konferenciji i mo\u0107i \u0107emo nastaviti ovaj dijalog. Vidimo se na Hydri!<\/p>\n<p><\/p>\n<blockquote><p>Mo\u017eete nastaviti razgovor s Cliffom na konferenciji Hydra 2019, koja \u0107e se odr\u017eati 11-12. srpnja 2019. godine u Sankt Peterburgu. On \u0107e do\u0107i s izlaganjem <noindex><a rel=\"nofollow\" href=\"https:\/\/hydraconf.com\/2019\/talks\/2jix5mst7iduyp9linqhfj\/?utm_source=habr&amp;utm_medium=45871\">\u00abIskustvo sa Azul Hardware Transactional Memory\u00bb<\/a><\/noindex>. Karte se mogu kupiti <noindex><a rel=\"nofollow\" href=\"https:\/\/hydraconf.ru\/?utm_source=habr&amp;utm_medium=458718\">na slu\u017ebenoj stranici<\/a><\/noindex>.<\/p><\/blockquote>\n<p>Izvor: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/jugru\/blog\/458718\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041a\u043b\u0438\u0444\u0444 \u041a\u043b\u0438\u043a \u2014 CTO \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 Cratus (IoT \u0441\u0435\u043d\u0441\u043e\u0440\u044b \u0434\u043b\u044f \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432), \u043e\u0441\u043d\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0438 \u0441\u043e\u043e\u0441\u043d\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u0442\u0430\u0440\u0442\u0430\u043f\u043e\u0432 (\u0432\u043a\u043b\u044e\u0447\u0430\u044f Rocket Realtime School, Neurensic \u0438 H2O.ai) \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u043c\u0438 \u044d\u043a\u0437\u0438\u0442\u0430\u043c\u0438. \u041a\u043b\u0438\u0444\u0444 \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0441\u0432\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0432 15 \u043b\u0435\u0442 (Pascal \u0434\u043b\u044f TRS Z-80)! \u041d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043d \u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 \u043d\u0430\u0434 \u04212 \u0432 Java (the Sea of Nodes IR). \u042d\u0442\u043e\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u043e\u043a\u0430\u0437\u0430\u043b [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-35851","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.4 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041a\u043b\u0438\u0444\u0444 \u041a\u043b\u0438\u043a \u2014.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"hr_HR\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0411\u043e\u043b\u044c\u0448\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e \u0441 \u041a\u043b\u0438\u0444\u0444\u043e\u043c \u041a\u043b\u0438\u043a\u043e\u043c \u2014 \u043e\u0442\u0446\u043e\u043c JIT-\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0432 Java | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041a\u043b\u0438\u0444\u0444 \u041a\u043b\u0438\u043a \u2014.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:07:03+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:07:03+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Veliki intervju s Cliffom Clickom \u2014 ocem JIT kompilacije u Javi | ProHoster","description":"Cliff Click \u2014.","canonical_url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"hr_HR","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0411\u043e\u043b\u044c\u0448\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e \u0441 \u041a\u043b\u0438\u0444\u0444\u043e\u043c \u041a\u043b\u0438\u043a\u043e\u043c \u2014 \u043e\u0442\u0446\u043e\u043c JIT-\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0432 Java | ProHoster","og:description":"\u041a\u043b\u0438\u0444\u0444 \u041a\u043b\u0438\u043a \u2014.","og:url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:07:03+00:00","article:modified_time":"2019-10-31T19:07:03+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"35851","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-22 01:01:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:55:25","updated":"2026-01-22 01:01:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/35851","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/comments?post=35851"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/35851\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media?parent=35851"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/categories?post=35851"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/tags?post=35851"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}