{"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\/ro\/blog\/administrirovanie\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java","title":{"rendered":"Interviu amplu cu Cliff Click \u2014 p\u0103rintele compil\u0103rii JIT \u00een Java","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Interviu amplu cu Cliff Click \u2014 p\u0103rintele compil\u0103rii JIT \u00een Java\" src=\"\/wp-content\/uploads\/2019\/07\/9ea9740ef74c0ae14d334482af115222.png\" style=\"display:block;margin: 0 auto;\" \/><strong>Cliff Click<\/strong> \u2014 CTO al companiei Cratus (senzori IoT pentru \u00eembun\u0103t\u0103\u021birea proceselor), fondator \u0219i cofondator al mai multor startup-uri (inclusiv Rocket Realtime School, Neurensic \u0219i H2O.ai) cu mai multe ie\u0219iri de succes. Cliff a scris primul s\u0103u compilator la 15 ani (Pascal pentru TRS Z-80)! Este cel mai cunoscut pentru munca sa asupra C2 \u00een Java (the Sea of Nodes IR). Acest compilator a ar\u0103tat lumii c\u0103 JIT poate produce cod de calitate, ceea ce a fost unul dintre factorii care au contribuit la emergen\u021ba Java ca una dintre principalele platforme software moderne. Apoi, Cliff a ajutat compania Azul Systems s\u0103 construiasc\u0103 un mainframe cu 864 de nuclee cu software \u00een Java pur, care suportea pauze GC pe un heap de 500 de gigaocte\u021bi \u00een cadrul a 10 milisecunde. De fapt, Cliff a reu\u0219it s\u0103 lucreze la toate aspectele JVM.<br clear=\"all\"><br \/>\n\u00a0<br \/>\nAcest post Habr este un interviu amplu cu Cliff. Vom discuta urm\u0103toarele subiecte:<\/p>\n<p><\/p>\n<ul>\n<li>Trecerea la optimiz\u0103ri de nivel sc\u0103zut<\/li>\n<li>Cum s\u0103 faci un refactoring mare<\/li>\n<li>Modelul de costuri<\/li>\n<li>\u00cenv\u0103\u021bare a optimiz\u0103rilor de nivel sc\u0103zut<\/li>\n<li>Exemple practice de \u00eembun\u0103t\u0103\u021bire a performan\u021bei<\/li>\n<li>De ce s\u0103 creezi propriul limbaj de programare<\/li>\n<li>Cariera unui inginer de performan\u021b\u0103<\/li>\n<li>Provoc\u0103rile tehnice<\/li>\n<li>Pu\u021bin despre alocarea registrelor \u0219i multicoeren\u021b\u0103<\/li>\n<li>Cea mai mare provocare din via\u021ba mea<\/li>\n<\/ul>\n<p><\/p>\n<p>Interviul este condus de:<\/p>\n<p><\/p>\n<ul>\n<li><strong>Andrei Satarin<\/strong> de la Amazon Web Services. \u00cen cariera sa, a reu\u0219it s\u0103 colaboreze la proiecte complet diferite: a testat o baz\u0103 de date distribuit\u0103 NewSQL la Yandex, un sistem de detectare \u00een cloud la Laboratorul Kaspersky, un joc multiplayer la Mail.ru \u0219i un serviciu de calcul al pre\u021burilor valutare la Deutsche Bank. Este interesat de testarea sistemelor backend la scar\u0103 mare \u0219i de sistemele distribuite.<\/li>\n<li><strong>Vladimir Sitnikov<\/strong> de la Netcracker. Lucreaz\u0103 de zece ani la performan\u021ba \u0219i scalabilitatea NetCracker OS \u2014 software utilizat de operatorii de telecomunica\u021bii pentru automatizarea proceselor de gestionare a re\u021belei \u0219i a echipamentului de re\u021bea. Este pasionat de problemele de performan\u021b\u0103 ale Java \u0219i Oracle Database. Autor al mai multor \u00eembun\u0103t\u0103\u021biri de performan\u021b\u0103 \u00een driverul oficial PostgreSQL JDBC.<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"perehod-k-nizkourovnevym-optimizaciyam\">Trecerea la optimiz\u0103ri de nivel sc\u0103zut<\/h1>\n<p><\/p>\n<p><strong>Andrei<\/strong>: E\u0219ti o persoan\u0103 cunoscut\u0103 \u00een lumea JIT-compilerii, \u00een Java \u0219i \u00een ceea ce prive\u0219te performan\u021ba \u00een general, nu-i a\u0219a?\u00a0<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: A\u0219a este!<\/p>\n<p><\/p>\n<p><strong>Andrei<\/strong>: S\u0103 \u00eencepem cu \u00eentreb\u0103ri generale despre munca pe performan\u021b\u0103. Ce p\u0103rere ai despre alegerea \u00eentre optimiz\u0103ri de nivel \u00eenalt \u0219i cele de nivel sc\u0103zut, cum ar fi lucrul la nivel de CPU?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Aici totul este simplu. Cea mai rapid\u0103 linie de cod este aceea care nu este niciodat\u0103 executat\u0103. Prin urmare, trebuie s\u0103 \u00eencepi \u00eentotdeauna de la un nivel \u00eenalt, lucr\u00e2nd la algoritmi. O notare O mai bun\u0103 va \u00eenvinge o notare O mai slab\u0103, cu excep\u021bia cazului \u00een care intervin unele constante destul de mari. Lucrurile de nivel sc\u0103zut vin \u00eentotdeauna ultimele. De obicei, dac\u0103 ai optimizat suficient restul stivei \u0219i mai r\u0103m\u00e2ne ceva interesant \u2013 aceasta este esen\u021ba nivelului sc\u0103zut. Dar cum \u00eencepi de la un nivel \u00eenalt? Cum \u0219tii c\u0103 ai f\u0103cut suficient\u0103 munc\u0103 la un nivel \u00eenalt? Ei bine\u2026 nu exist\u0103. Nu exist\u0103 re\u021bete gata f\u0103cute. Trebuie s\u0103 \u00een\u021belegi problema, s\u0103 decizi ce vrei s\u0103 faci (pentru a nu face pa\u0219i nefolositori ulterior) \u0219i atunci po\u021bi scoate profilerul, care poate spune ceva util. La un moment dat, \u00ee\u021bi dai seama singur c\u0103 ai sc\u0103pat de lucrurile inutile \u0219i c\u0103 a sosit momentul s\u0103 te ocupi de ajust\u0103rile fine de nivel sc\u0103zut. Cu siguran\u021b\u0103, aceasta este o form\u0103 special\u0103 de art\u0103. Mul\u021bi oameni fac lucruri inutile, dar se mi\u0219c\u0103 at\u00e2t de repede, \u00eenc\u00e2t nu au timp s\u0103 se preocupe de performan\u021b\u0103. Dar asta este p\u00e2n\u0103 c\u00e2nd problema devine critic\u0103. De obicei, 99% din timp nim\u0103nui nu-i pas\u0103 de ce fac, p\u00e2n\u0103 \u00een momentul \u00een care pe drumul critic apare ceva important, care devine de interes pentru cineva. \u0218i atunci to\u021bi \u00eencep s\u0103 te \u00eentrebe \u201ede ce nu a func\u021bionat perfect de la \u00eenceput\u201d. \u00cen general, \u00eentotdeauna exist\u0103 ceva de \u00eembun\u0103t\u0103\u021bit \u00een performan\u021b\u0103. Dar 99% din timp nu ai indicii! \u00cencerci pur \u0219i simplu s\u0103 faci ceva s\u0103 func\u021bioneze \u0219i descoperi \u00een acest proces ce este important. Nu po\u021bi \u0219ti niciodat\u0103 dinainte c\u0103 acest fragment trebuie s\u0103 fie perfect, a\u0219a c\u0103, \u00een esen\u021b\u0103, trebuie s\u0103 fii perfect \u00een tot. \u0218i aceasta este imposibil \u0219i nu faci a\u0219a. \u00centotdeauna exist\u0103 o mul\u021bime de lucruri de reparat \u2013 \u0219i asta este perfect normal.<\/p>\n<p><\/p>\n<h1 id=\"kak-delat-bolshoy-refaktoring\">Cum s\u0103 faci un refactoring mare<\/h1>\n<p><\/p>\n<p><strong>Andrei<\/strong>: Cum lucra\u021bi la performan\u021b\u0103? Este o problem\u0103 transversal\u0103. De exemplu, a trebuit vreodat\u0103 s\u0103 lucrezi la probleme care apar \u00een urma suprapunerii unui num\u0103r mare de func\u021bionalit\u0103\u021bi existente?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Evit acest lucru. Dac\u0103 \u0219tiu c\u0103 performan\u021ba va fi o problem\u0103, m\u0103 g\u00e2ndesc la asta \u00eenainte de a \u00eencepe s\u0103 codez, mai ales la structurile de date. Dar adesea descoperi toate acestea mult mai t\u00e2rziu. \u0218i atunci trebuie s\u0103 recurgi la m\u0103suri extreme \u0219i s\u0103 faci ceea ce numesc \u201erescrie \u0219i domin\u0103\u201d: trebuie s\u0103 te apuci de o bucat\u0103 destul de mare. O parte din cod tot va trebui rescris\u0103 din cauza problemelor de performan\u021b\u0103 sau din alte motive. Indiferent de motivul pentru care trebuie s\u0103 rescrii codul, aproape \u00eentotdeauna este mai bine s\u0103 rescrii o bucat\u0103 mai mare dec\u00e2t una mai mic\u0103. \u00cen acel moment, toat\u0103 lumea \u00eencepe s\u0103 tremure de fric\u0103: \u201eoh, Doamne, nu po\u021bi s\u0103 atingi at\u00e2t de mult cod!\u201d. Dar, de fapt, aceast\u0103 abordare func\u021bioneaz\u0103 aproape \u00eentotdeauna mult mai bine. Trebuie s\u0103 te apuci din start de o problem\u0103 mare, s\u0103 conturezi un cerc mare \u00een jurul ei \u0219i s\u0103 spui: tot ce e \u00een interiorul cercului, voi rescrie. Limita este cu mult mai mic\u0103 dec\u00e2t con\u021binutul care trebuie \u00eenlocuit din interior. \u0218i dac\u0103 aceast\u0103 conturare a limitelor permite s\u0103 faci treaba din\u0103untru perfect \u2013 e\u0219ti liber, f\u0103 ce vrei. Odat\u0103 ce ai \u00een\u021beles problema, procesul de rescriere decurge mult mai u\u0219or, a\u0219a c\u0103 ia o bucat\u0103 mare!<br \/>\n\u00cen acela\u0219i timp, atunci c\u00e2nd rescrii o bucat\u0103 mare \u0219i realizezi c\u0103 performan\u021ba va fi o problem\u0103, po\u021bi \u00eencepe imediat s\u0103 te \u00eengrijorezi \u00een leg\u0103tur\u0103 cu aceasta. De obicei, se transform\u0103 \u00een lucruri simple precum \u201enu copia datele, gestioneaz\u0103 datele c\u00e2t mai simplu posibil, f\u0103-le mai mici\u201d. \u00cen rescrierile mari, exist\u0103 modalit\u0103\u021bi standard de a \u00eembun\u0103t\u0103\u021bi performan\u021ba. \u0218i acestea se \u00eenv\u00e2rt aproape \u00eentotdeauna \u00een jurul datelor.<\/p>\n<p><\/p>\n<h1 id=\"model-stoimosti\">Modelul de costuri<\/h1>\n<p><\/p>\n<p><strong>Andrei<\/strong>: \u00cen unul dintre podcasturi ai vorbit despre modelele de costuri \u00een contextul performan\u021bei. Po\u021bi explica ce ai vrut s\u0103 spui prin asta?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Desigur. M-am n\u0103scut \u00eentr-o epoc\u0103 \u00een care performan\u021ba procesorului era extrem de important\u0103. \u0218i aceast\u0103 er\u0103 revine din nou \u2013 soarta nu e lipsit\u0103 de ironie. Am \u00eenceput s\u0103 tr\u0103iesc \u00een vremurile ma\u0219inilor pe 8 bi\u021bi, primul meu computer func\u021biona cu 256 de bi\u021bi. A fost absolut mic. Trebuia s\u0103 num\u0103r instruc\u021biunile \u0219i, pe m\u0103sur\u0103 ce am \u00eenceput s\u0103 avans\u0103m \u00een ierarhia limbajelor de programare, limbajele \u00ee\u0219i asumau din ce \u00een ce mai multe responsabilit\u0103\u021bi. A fost Assembler, apoi Basic, apoi C, iar C prelua sarcini legate de multe detalii, cum ar fi alocarea registrelor \u0219i selec\u021bia instruc\u021biunilor. Dar acolo totul era destul de clar \u0219i, dac\u0103 am creat un pointer la o instan\u021b\u0103 a unei variabile, atunci voi ob\u021bine un load, iar costul acestei instruc\u021biuni este cunoscut. Hardware-ul ofer\u0103 un num\u0103r cunoscut de cicluri ma\u0219in\u0103, astfel c\u0103 viteza de execu\u021bie a diferitelor opera\u021bii poate fi calculat\u0103 simplu prin adunarea tuturor instruc\u021biunilor pe care inten\u021bionezi s\u0103 le execu\u021bi. Fiecare compare\/test\/branch\/call\/load\/store putea fi adunat \u0219i putea fi spus: iat\u0103, aceasta este timpul de execu\u021bie. Atunci c\u00e2nd te ocupi cu \u00eembun\u0103t\u0103\u021birea performan\u021bei, cu siguran\u021b\u0103 vei observa ce numere corespund ciclurilor fierbin\u021bi de mic\u0103 amploare.\u00a0<br \/>\nDar de \u00eendat\u0103 ce te schimbi pe Java, Python \u0219i lucruri asem\u0103n\u0103toare, te \u00eendep\u0103rtezi foarte repede de hardware-ul de nivel sc\u0103zut. Care este costul apelului getter \u00een Java? Dac\u0103 JIT \u00een HotSpot face totul corect <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.openjdk.java.net\/display\/HotSpot\/Inlining\">inlined<\/a><\/noindex>, acesta va fi un load, dar, dac\u0103 nu a f\u0103cut asta \u2013 va fi un apel de func\u021bie. Deoarece apelul se afl\u0103 \u00een ciclul fierbinte, va anula toate celelalte optimiz\u0103ri din acel ciclu. Prin urmare, costul real va fi mult mai mare. \u0218i pierzi imediat capacitatea de a privi un segment de cod \u0219i de a \u00een\u021belege c\u00e2t de mult ar trebui s\u0103-l execut\u0103m \u00een termeni de frecven\u021b\u0103 de ceas a procesorului, memorie utilizat\u0103 \u0219i cache. Totul devine interesant doar dac\u0103 te aprofundezi \u00een performan\u021b\u0103.<br \/>\nAcum ne afl\u0103m \u00eentr-o situa\u021bie \u00een care vitezele procesoarelor aproape c\u0103 nu au crescut timp de un deceniu. Timpurile vechi revin! Nu te mai po\u021bi baza pe o performan\u021b\u0103 bun\u0103 pe un singur fir de execu\u021bie. Dar dac\u0103 te-ai apuca de calcul paralel \u2013 este extrem de complicat, to\u021bi se uit\u0103 la tine ca la James Bond. Acceler\u0103rile de zece ori apar de obicei acolo unde cineva a ratat ceva. Paralelismul necesit\u0103 mult\u0103 munc\u0103. Pentru a ob\u021bine acel accelerare de zece ori, trebuie s\u0103 \u00een\u021belegi modelul de cost. Ce cost\u0103 \u0219i c\u00e2t cost\u0103. Iar pentru asta trebuie s\u0103 \u00een\u021belegi cum se potrive\u0219te limbajul pe hardware-ul de baz\u0103.<br \/>\nMartin Thompson a g\u0103sit un cuv\u00e2nt minunat pentru blogul s\u0103u <noindex><a rel=\"nofollow\" href=\"https:\/\/mechanical-sympathy.blogspot.com\/\">Simpatia Mechanical<\/a><\/noindex>! Este necesar s\u0103 \u00een\u021belegi ce va face hardware-ul, cum anume va face asta \u0219i de ce face ceea ce face. Folosind aceste informa\u021bii, este destul de simplu s\u0103 \u00eencepi s\u0103 num\u0103re\u021bi instruc\u021biunile \u0219i s\u0103 afli unde se duce timpul de execu\u021bie. Dac\u0103 nu ai preg\u0103tirea corespunz\u0103toare, cau\u021bi doar o pisic\u0103 neagr\u0103 \u00eentr-o camer\u0103 \u00eentunecat\u0103. V\u0103d constant oameni care optimizeaz\u0103 performan\u021ba, f\u0103r\u0103 s\u0103 aib\u0103 cele mai mici idei despre ce naiba fac de fapt. Se chinuie foarte mult \u0219i nu avanseaz\u0103 deloc. \u0218i c\u00e2nd iau acela\u0219i fragment de cod, adaug c\u00e2teva trucuri simple \u0219i ob\u021bin o accelerare de cinci sau zece ori, ei spun: \u201eEh, asta nu este cinstit, \u0219tim deja c\u0103 e\u0219ti mai bun.\u201d Uimitor. Despre ce vorbeam\u2026 modelul de cost \u2013 este despre ce cod scrii \u0219i c\u00e2t de repede func\u021bioneaz\u0103 acesta \u00een imaginea de ansamblu.<\/p>\n<p><\/p>\n<p><strong>Andrei<\/strong>: \u0218i cum re\u021bii un astfel de volum \u00een minte? Se atinge prin mult\u0103 experien\u021b\u0103, nu-i a\u0219a? De unde se dob\u00e2nde\u0219te astfel de experien\u021b\u0103?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Ei bine, experien\u021ba mea nu a venit pe cel mai simplu drum. Am programat \u00een Assembler \u00een vremurile c\u00e2nd putea s\u0103 \u00een\u021belegi fiecare instruc\u021biune \u00een parte. Sun\u0103 prostie, dar de atunci am un set de instruc\u021biuni Z80 \u00een cap, \u00een memorie, pentru totdeauna. Nu-mi amintesc numele oamenilor la un minut dup\u0103 o discu\u021bie, dar \u00eemi amintesc codul scris acum 40 de ani. Amuzant, arat\u0103 ca un sindrom de \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\">geniu idiot<\/a><\/noindex>\u00bb.<\/p>\n<p><\/p>\n<h1 id=\"obuchenie-nizkourovnevym-optimizaciyam\">\u00cenv\u0103\u021bare a optimiz\u0103rilor de nivel sc\u0103zut<\/h1>\n<p><\/p>\n<p><strong>Andrei<\/strong>: Exist\u0103 o modalitate mai simpl\u0103 de a intra \u00een domeniu?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Da \u0219i nu. Echipamentele pe care le folosim nu s-au schimbat at\u00e2t de mult \u00een aceast\u0103 perioad\u0103. Toat\u0103 lumea folose\u0219te x86, cu excep\u021bia smartphone-urilor care func\u021bioneaz\u0103 pe Arm. Dac\u0103 nu te ocupi de ceva foarte avansat \u00een embeddeding, ai acelea\u0219i lucruri. Bine, s\u0103 continu\u0103m. Instruc\u021biunile nu s-au schimbat de secole. Trebuie s\u0103 mergi \u0219i s\u0103 scrii ceva \u00een Assembler. Pu\u021bin, dar suficient pentru a \u00eencepe s\u0103 \u00een\u021belegi. Tu r\u00e2zi, dar eu vorbesc serios. Trebuie s\u0103 \u00een\u021belegi coresponden\u021ba dintre limbaj \u0219i hardware. Dup\u0103 aceea, trebuie s\u0103 mergi, s\u0103 scrii pu\u021bin \u0219i s\u0103 creezi un mic compilator de joc pentru un mic limbaj de joc. \u201eJoc\u201d \u00eenseamn\u0103 c\u0103 trebuie s\u0103-l faci \u00eentr-un timp rezonabil. Poate fi super simplu, dar trebuie s\u0103 genereze instruc\u021biuni. Actul gener\u0103rii instruc\u021biunilor va permite s\u0103 \u00een\u021belegi modelul de cost pentru puntea \u00eentre codul de nivel \u00eenalt, pe care toat\u0103 lumea \u00eel scrie, \u0219i codul ma\u0219in\u0103 care ruleaz\u0103 pe hardware. Aceast\u0103 coresponden\u021b\u0103 se va \u00eentip\u0103ri \u00een minte \u00een momentul \u00een care scrii compilatorul. Chiar \u0219i cel mai simplu compilator. Dup\u0103 aceea, po\u021bi \u00eencepe s\u0103 te ui\u021bi la Java \u0219i s\u0103 vezi c\u0103 exist\u0103 o pr\u0103pastie semantic\u0103 mult mai profund\u0103, iar construirea de pun\u021bi peste aceasta este mult mai complicat\u0103. \u00cen Java, este mult mai greu s\u0103 \u00een\u021belegi dac\u0103 puntea noastr\u0103 este bun\u0103 sau proast\u0103, ce o va face s\u0103 se pr\u0103bu\u0219easc\u0103 \u0219i ce nu. Dar ai nevoie de un punct de plecare, c\u00e2nd te ui\u021bi la cod \u0219i \u00een\u021belegi: \u201eaha, acest getter ar trebui s\u0103 fie inlinat de fiecare dat\u0103\u201d. \u0218i se dovede\u0219te c\u0103 uneori se \u0219i \u00eent\u00e2mpl\u0103, cu excep\u021bia cazului \u00een care metoda devine prea mare \u0219i JIT \u00eencepe s\u0103 inlinieze tot. Performan\u021ba acestor locuri poate fi prezis\u0103 instantaneu. De obicei, gettere func\u021bioneaz\u0103 bine, dar apoi te ui\u021bi la buclele mari \u0219i fierbin\u021bi \u0219i \u00een\u021belegi c\u0103 exist\u0103 apeluri de func\u021bii care nu este clar ce fac. Aici este problema cu utilizarea pe scar\u0103 larg\u0103 a getterelor, motivul pentru care nu se inliniaz\u0103 \u2013 nu este clar dac\u0103 este un getter. Dac\u0103 ai o baz\u0103 de cod foarte mic\u0103, po\u021bi pur \u0219i simplu s\u0103 o memorezi \u0219i apoi s\u0103 spui: acesta este un getter, iar acesta este un setter. \u00centr-o baz\u0103 de cod mare, fiecare func\u021bie are propria sa poveste, care nu este cunoscut\u0103 nim\u0103nui. Profilatorul spune c\u0103 am pierdut 24% din timp pe un anumit ciclu \u0219i, pentru a \u00een\u021belege ce face acest ciclu, trebuie s\u0103 te ui\u021bi la fiecare func\u021bie din interior. Nu po\u021bi s\u0103 \u00een\u021belegi asta f\u0103r\u0103 a studia func\u021bia, \u0219i acest lucru \u00eencetine\u0219te serios procesul de \u00een\u021belegere. De aceea nu folosesc gettere \u0219i settere, am trecut la un nou nivel!<br \/>\nDe unde pot ob\u021bine un model de costuri? Ei bine, pot citi ceva, desigur... Dar cred c\u0103 cea mai bun\u0103 modalitate este s\u0103 ac\u021bionez. S\u0103 fac un mic compilator \u0219i acesta va fi cel mai bun mod de a \u00een\u021belege modelul de costuri \u0219i de a-l \u00eencorpora \u00een propria mea g\u00e2ndire. Un mic compilator care ar putea fi folosit pentru programarea unui cuptor cu microunde \u2013 aceasta este o sarcin\u0103 pentru \u00eencep\u0103tori. Adic\u0103, dac\u0103 deja ai abilit\u0103\u021bi de programare, ar trebui s\u0103 fie suficient. Toate aceste lucruri, cum ar fi parcurgerea unei stringa care va fi o expresie algebraic\u0103, scoaterea instruc\u021biunilor opera\u021biunilor matematice \u00een ordinea corect\u0103, ob\u021binerea valorilor corecte din registre \u2013 toate acestea se fac rapid. \u0218i \u00een timp ce faci asta, se va imprima \u00een minte. Cred c\u0103 toat\u0103 lumea \u0219tie ce face un compilator. \u0218i aceasta va oferi o \u00een\u021belegere a modelului de costuri.<\/p>\n<p><\/p>\n<h1 id=\"prakticheskie-primery-uluchsheniya-proizvoditelnosti\">Exemple practice de \u00eembun\u0103t\u0103\u021bire a performan\u021bei<\/h1>\n<p><\/p>\n<p><strong>Andrei<\/strong>: La ce altceva ar trebui s\u0103 fiu atent c\u00e2nd lucrez la performan\u021b\u0103?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Structuri de date. Apropo, da, nu am mai sus\u021binut aceste cursuri de mult timp... <noindex>Rocket School<\/noindex>. A fost amuzant, dar necesita at\u00e2t de mult efort, iar eu mai am \u0219i via\u021ba mea! Bine. A\u0219adar, \u00eentr-una din lec\u021biile mari \u0219i interesante, \u201eUnde se duce performan\u021ba ta\u201d, le-am dat studen\u021bilor un exemplu: dou\u0103 giga \u0219i jum\u0103tate de date fintech erau citite dintr-un fi\u0219ier CSV \u0219i apoi trebuia s\u0103 calculez num\u0103rul produselor v\u00e2ndute. Datele pie\u021bei de tip tic. Pachete UDP, transformate \u00een format text, \u00eencep\u00e2nd cu anii 70. Chicago Mercantile Exchange \u2013 tot felul de lucruri cum ar fi uleiul, porumbul, soia \u0219i a\u0219a mai departe. Trebuia s\u0103 num\u0103r aceste produse, num\u0103rul tranzac\u021biilor, volumul mediu al mi\u0219c\u0103rilor de fonduri \u0219i bunuri etc. Este matematic\u0103 de tranzac\u021bionare destul de simpl\u0103: g\u0103se\u0219te codul produsului (acesta este 1-2 caractere \u00een tabela de hash), ob\u021bine suma, adaug\u0103-o \u00eentr-unul din seturile de tranzac\u021bii, adaug\u0103 volumul, adaug\u0103 costul \u0219i c\u00e2teva alte lucruri. O matematic\u0103 foarte simpl\u0103. Implementarea ludic\u0103 a fost foarte direct\u0103: totul se afl\u0103 \u00eentr-un fi\u0219ier, citesc fi\u0219ierul \u0219i m\u0103 mi\u0219c pe el, separ\u00e2nd \u00eenregistr\u0103rile individuale \u00een stringuri Java, caut \u00een ele lucrurile necesare \u0219i le adun conform matematicii descrise mai sus. \u0218i acest lucru func\u021bioneaz\u0103 cu o vitez\u0103 oarecare. <\/p>\n<p><\/p>\n<p>Cu aceast\u0103 abordare, totul este evident, ceea ce se \u00eent\u00e2mpl\u0103, \u0219i computa\u021biile paralele nu vor ajuta aici, nu? Se pare c\u0103 o cre\u0219tere a performan\u021bei de cinci ori poate fi ob\u021binut\u0103 doar prin alegerea structurilor de date potrivite. \u0218i acest lucru \u00eei surprinde chiar \u0219i pe programatorii experimenta\u021bi! \u00cen cazul meu specific, accentul a fost pe faptul c\u0103 nu ar trebui s\u0103 fac aloc\u0103ri de memorie \u00een buclele frecvente. Ei bine, aceasta nu este toat\u0103 adev\u0103rul, dar \u00een general \u2013 nu este bine s\u0103 aloci \u201eodat\u0103 la X\u201d, c\u00e2nd X este suficient de mare. C\u00e2nd X este de dou\u0103 ori \u0219i jum\u0103tate de gigabyte, nu ar trebui s\u0103 aloci nimic \u201eodat\u0103 pentru liter\u0103\u201d, sau \u201eodat\u0103 pentru linie\u201d, sau \u201eodat\u0103 pentru c\u00e2mp\u201d, nimic de acest fel. Aici se pierde timpul. Cum func\u021bioneaz\u0103 acest lucru? Imagineaz\u0103-\u021bi c\u0103 fac o apelare <code>String.split()<\/code> sau <code>BufferedReader.readLine()<\/code>. <code>Readline<\/code> face un \u0219ir dintr-un set de octe\u021bi care vin prin re\u021bea, o dat\u0103 pentru fiecare linie, pentru fiecare dintre sutele de milioane de linii. Eu iau acest \u0219ir, \u00eel analizez \u0219i \u00eel arunc. De ce \u00eel arunc \u2013 ei bine, eu l-am procesat deja, tot. A\u0219adar, pentru fiecare octet citit din acele 2.7G, vor fi scrise dou\u0103 caractere \u00een \u0219ir, adic\u0103 deja 5.4G, iar acestea nu \u00eemi mai sunt necesare, a\u0219a c\u0103 sunt aruncate. Dac\u0103 ne uit\u0103m la l\u0103\u021bimea de band\u0103 a memoriei, \u00eenc\u0103rc\u0103m 2.7G, care trec prin memorie \u0219i magistrala de memorie \u00een procesor, \u0219i mai departe se trimit de dou\u0103 ori mai multe \u00een \u0219irul aflat \u00een memorie, \u0219i toate acestea sunt procesate la crearea fiec\u0103rui nou \u0219ir. Dar trebuie s\u0103 \u00eel citesc, hardware-ul \u00eel cite\u0219te, chiar dac\u0103 dup\u0103 aceea totul va fi procesat. \u0218i trebuie s\u0103 \u00eel scriu, pentru c\u0103 am creat un \u0219ir \u0219i cache-urile au fost umplute \u2013 cache-ul nu poate re\u021bine 2.7G. \u00cen total, pentru fiecare octet citit, citesc \u00eenc\u0103 dou\u0103 octe\u021bi suplimentari \u0219i scriu doi octe\u021bi suplimentari, \u0219i \u00een cele din urm\u0103, au un raport de 4:1 \u2013 \u00eentr-un astfel de raport, risipim l\u0103\u021bimea de band\u0103 a memoriei. Apoi se dovede\u0219te c\u0103 dac\u0103 fac <code>String.split()<\/code> \u2013 atunci o fac departe de ultima dat\u0103, acolo pot fi \u00eenc\u0103 6-7 c\u00e2mpuri. A\u0219adar, codul clasic de citire CSV cu parsarea ulterioar\u0103 a \u0219irurilor duce la pierderi de l\u0103\u021bime de band\u0103 a memoriei de aproximativ 14:1 fa\u021b\u0103 de ceea ce ai dori, de fapt, s\u0103 ai. Dac\u0103 elimini aceste aloc\u0103ri, po\u021bi ob\u021bine o accelerare de cinci ori. <\/p>\n<p><\/p>\n<p>\u0218i nu este foarte complicat. Dac\u0103 prive\u0219ti codul din unghiul corect, totul devine destul de simplu imediat ce ai \u00een\u021beles esen\u021ba problemei. Nu trebuie s\u0103 \u00eencetezi s\u0103 aloci memorie: problema este c\u0103 aloci ceva \u0219i imediat se pierde, iar pe parcurs consum\u0103 o resurs\u0103 important\u0103, care \u00een acest caz este l\u0103\u021bimea de band\u0103 a memoriei. \u0218i totul se traduce \u00eentr-o sc\u0103dere a performan\u021bei. Pe x86, de obicei, trebuie s\u0103 utilizezi activ ciclurile procesorului, dar aici ai ars toat\u0103 memoria mult mai devreme. Solu\u021bia este s\u0103 reduci num\u0103rul de aloc\u0103ri.\u00a0<br \/>\nO alt\u0103 parte a problemei este c\u0103, dac\u0103 porne\u0219ti un profiler atunci c\u00e2nd l\u0103\u021bimea de band\u0103 a memoriei s-a epuizat, exact \u00een momentul \u00een care se \u00eent\u00e2mpl\u0103 acest lucru, a\u0219tep\u021bi de obicei s\u0103 revin\u0103 cache-ul, deoarece este plin de zgomotul pe care tocmai l-ai generat, cu toate acele stringuri. Prin urmare, fiecare opera\u021biune load sau store devine lent\u0103, deoarece duc la erori \u00een cache \u2013 \u00eentregul cache a devenit lent, a\u0219tept\u00e2nd s\u0103 fie eliberat de zgomot. De aceea, profilerul va ar\u0103ta doar o zgomot aleatoriu cald, \u00eentins pe tot ciclul \u2013 nu va exista nicio instruc\u021biune sau loc \u00een cod care s\u0103 fie fierbinte. Numai zgomot. \u0218i dac\u0103 te ui\u021bi la ciclurile GC, toate vor fi pe Young Generation \u0219i foarte rapide \u2013 microsecunde sau milisecunde maxim. Deoarece toat\u0103 aceast\u0103 memorie moare instantaneu. Aloci miliarde de gigaocte\u021bi, \u0219i el le elimin\u0103, \u0219i le elimin\u0103, \u0219i din nou le elimin\u0103. Totul se \u00eent\u00e2mpl\u0103 foarte rapid. A\u0219adar, ai cicluri GC ieftine, zgomot cald pe parcursul \u00eentregului ciclu, dar ne dorim o accelerare de 5 ori. \u00cen acel moment, ar trebui s\u0103 \u00ee\u021bi fac\u0103 ceva click \u00een minte \u0219i s\u0103 sune: \u201ede ce a\u0219a?!\u201d. Supra\u00eenc\u0103rcarea l\u0103\u021bimii de band\u0103 a memoriei nu se reflect\u0103 \u00een debugger-ul standard, trebuie s\u0103 porne\u0219ti un debugger pentru contoarele de performan\u021b\u0103 hardware \u0219i s\u0103 vezi asta singur \u0219i direct. Iar indirect, acesta poate fi suspectat din aceste trei simptome. Al treilea simptom este atunci c\u00e2nd te ui\u021bi ce aloci, \u00eentrebi profiler-ul, iar el r\u0103spunde: \u201eAi f\u0103cut miliarde de stringuri, dar GC a func\u021bionat gratuit\u201d. Odat\u0103 ce s-a \u00eent\u00e2mplat asta, \u00een\u021belegi c\u0103 ai generat prea multe obiecte \u0219i ai ars \u00eentreaga l\u0103\u021bime de band\u0103 a memoriei. Exist\u0103 o modalitate de a \u00een\u021belege asta, dar nu este evident\u0103.\u00a0<\/p>\n<p><\/p>\n<p>Problema se afl\u0103 \u00een structura datelor: structura pur\u0103, care st\u0103 la baza a tot ce se \u00eent\u00e2mpl\u0103, este prea mare, are 2.7G pe disc, a\u0219a c\u0103 este foarte nedorit s\u0103 faci o copie a acestei lucruri \u2014 preferi s\u0103 o \u00eencarci direct din bufferul de bytes de re\u021bea \u00een registre, pentru a nu citi-scrie \u00een \u0219ir de mai multe ori. Din p\u0103cate, Java nu \u00ee\u021bi ofer\u0103 o astfel de bibliotec\u0103 \u00een JDK. Dar este un lucru trivial, nu-i a\u0219a? Practic, sunt 5-10 linii de cod care vor implementa un loader de \u0219iruri cu buffer, care reproduce comportamentul clasei \u015fir, ac\u021bion\u00e2nd ca un wrapper \u00een jurul bufferului de bytes de baz\u0103. Ca rezultat, ajungi s\u0103 lucrezi aproape ca \u0219i cum ai lucra cu \u0219iruri, dar, de fapt, acolo se mi\u0219c\u0103 pointeri c\u0103tre buffer, iar bytes brut nu sunt copiate nic\u0103ieri, astfel reutiliz\u00e2nd mereu acelea\u0219i buffere, de nenum\u0103rate ori, iar sistemul de operare este fericit s\u0103 preia lucrurile pentru care este destinat, precum dublarea ascuns\u0103 a acestor buffere de bytes, iar tu nu mai procesezi un flux infinit de date inutile. Apropo, cu siguran\u021b\u0103 \u0219ti\u021bi c\u0103, atunci c\u00e2nd lucrezi cu GC, este garantat c\u0103 fiecare alocare de memorie nu va fi vizibil\u0103 procesorului dup\u0103 ultimul ciclu de GC? A\u0219a c\u0103, tot acest lucru nu poate fi \u00een cache, iar mai departe se \u00eent\u00e2mpl\u0103 un miss garantat de 100%. C\u00e2nd lucrezi cu un pointer, pe x86, citirea unui registru din memorie dureaz\u0103 1-2 cicluri, \u0219i imediat ce se \u00eent\u00e2mpl\u0103 acest lucru, pl\u0103te\u0219ti, pl\u0103te\u0219ti, pl\u0103te\u0219ti, pentru c\u0103 toat\u0103 memoria <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Cache_inclusion_policy\">NINE cache-uri<\/a><\/noindex> \u2013 \u0219i aceasta este costul aloc\u0103rii memoriei. Costul real.<\/p>\n<p><\/p>\n<p>Pe scurt, structurile de date sunt cele mai greu de schimbat. Odat\u0103 ce realizezi c\u0103 ai ales o structur\u0103 de date gre\u0219it\u0103 care \u00ee\u021bi va afecta performan\u021ba pe viitor, de obicei, este necesar s\u0103 faci un efort considerabil, dar dac\u0103 nu o faci, lucrurile vor deveni mai dificile. \u00cen primul r\u00e2nd, trebuie s\u0103 te g\u00e2nde\u0219ti la structurile de date, acest aspect este important. Principalul cost provine din structuri de date elaborate, folosite \u00een stilul \u201eam copiat structura de date X \u00een structura de date Y pentru c\u0103 Y \u00eemi place mai mult ca aspect\u201d. Totu\u0219i, opera\u021bia de copiere (care pare ieftin\u0103) consum\u0103 de fapt l\u0103\u021bimea de band\u0103 a memoriei \u0219i aici se afl\u0103 tot timpul pierdut. Dac\u0103 am un \u0219ir gigantic de JSON \u0219i vreau s\u0103-l transform \u00eentr-un arbore DOM structurat din POJO sau ceva similar, opera\u021bia de parsare a acestui \u0219ir \u0219i construirea POJO, iar apoi accesarea nou\u0103 a POJO va conduce la costuri suplimentare - lucru care nu este ieftin. Cu excep\u021bia cazului \u00een care vei accesa POJO mult mai des dec\u00e2t \u0219irul. La o adic\u0103, po\u021bi \u00eencerca s\u0103 decodifici \u0219irul \u0219i s\u0103 extragi doar ceea ce ai nevoie, f\u0103r\u0103 a-l transforma \u00een POJO. Dac\u0103 toate acestea se \u00eent\u00e2mpl\u0103 \u00eentr-un context \u00een care se cere performan\u021b\u0103 maxim\u0103, evit\u0103 POJO - trebuie s\u0103 interac\u021bionezi direct cu \u0219irul.<\/p>\n<p><\/p>\n<h1 id=\"zachem-sozdavat-svoy-yazyk-programmirovaniya\">De ce s\u0103 creezi propriul limbaj de programare<\/h1>\n<p><\/p>\n<p><strong>Andrei<\/strong>: Ai spus c\u0103 pentru a \u00een\u021belege modelul de cost, trebuie s\u0103 \u00ee\u021bi scrii un mic limbaj...<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Nu un limbaj, ci un compilator. Limbajul \u0219i compilatorul sunt lucruri diferite. Cea mai important\u0103 distinc\u021bie este \u00een mintea ta.\u00a0<\/p>\n<p><\/p>\n<p><strong>Andrei<\/strong>: Apropo, din c\u00e2te \u0219tiu, experimentezi cu crearea propriilor limbaje. De ce?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Pentru c\u0103 pot! Sunt pe jum\u0103tate pensionat, a\u0219a c\u0103 acesta este hobby-ul meu. \u00centreaga mea via\u021b\u0103 am implementat limbajele altora. De asemenea, am lucrat mult la stilul de codare. \u0218i pentru c\u0103 v\u0103d probleme \u00een alte limbaje. Observ c\u0103 exist\u0103 modalit\u0103\u021bi mai bune de a face lucrurile obi\u0219nuite. \u0218i a\u0219 profita de ele. M-am s\u0103turat s\u0103 v\u0103d probleme \u00een mine, \u00een Java, \u00een Python, \u00een orice alt limbaj. Acum scriu \u00een React Native, JavaScript \u0219i Elm ca un hobby care nu este legat de pensionare, ci de o munc\u0103 activ\u0103. Scriu \u0219i \u00een Python \u0219i, cel mai probabil, voi continua s\u0103 lucrez la \u00eenv\u0103\u021barea automat\u0103 pentru backend-urile Java. Exist\u0103 multe limbaje populare \u0219i fiecare are tr\u0103s\u0103turi interesante. Fiecare este bun \u00een felul s\u0103u \u0219i po\u021bi \u00eencerca s\u0103 le unifici toate aceste tr\u0103s\u0103turi. A\u0219a c\u0103 m\u0103 dedic studiului lucrurilor interesante pentru mine, comportamentul limbajului, \u00eencerc\u00e2nd s\u0103 inventez o semantic\u0103 rezonabil\u0103. \u0218i p\u00e2n\u0103 acum reu\u0219esc!\u00cen acest moment, m\u0103 confrunt cu semantic\u0103 memoriei, deoarece vreau s\u0103 o am precum \u00een C \u0219i Java \u0219i s\u0103 ob\u021bin un model puternic de memorie \u0219i semantic\u0103 pentru loaduri \u0219i store-uri. \u00cen acela\u0219i timp, vreau s\u0103 am un tip de inferen\u021b\u0103 automat\u0103 precum \u00een Haskell. A\u0219adar, \u00eencerc s\u0103 combin inferen\u021ba tipurilor asem\u0103n\u0103toare cu Haskell cu o memorie care func\u021bioneaz\u0103 ca \u00een C \u0219i Java. Acest lucru m\u0103 ocup de 2-3 luni, de exemplu.<\/p>\n<p><\/p>\n<p><strong>Andrei<\/strong>: Dac\u0103 construie\u0219ti un limbaj care preia cele mai bune aspecte din alte limbaje, te-ai g\u00e2ndit c\u0103 cineva ar face invers: ar prelua ideile tale \u0219i le-ar folosi la el?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Exact a\u0219a apar noile limbaje! De ce Java este similar cu C? Pentru c\u0103 C avea o sintax\u0103 bun\u0103 pe care toat\u0103 lumea o \u00een\u021belegea, iar Java s-a inspirat din aceast\u0103 sintax\u0103, ad\u0103ug\u00e2nd acolo siguran\u021ba tipurilor, verific\u0103ri ale limitelor tabloului, GC, \u0219i de asemenea au \u00eembun\u0103t\u0103\u021bit anumite lucruri din C. Au ad\u0103ugat ale lor. Dar s-au inspirat destul de mult, nu-i a\u0219a? To\u021bi st\u0103m pe umerii gigantilor care au fost \u00eenaintea ta \u2013 a\u0219a se face progresul.<\/p>\n<p><\/p>\n<p><strong>Andrei<\/strong>: Din c\u00e2te \u00een\u021beleg, limbajul t\u0103u va fi sigur \u00een leg\u0103tur\u0103 cu utilizarea memoriei. Te-ai g\u00e2ndit s\u0103 implementezi ceva asem\u0103n\u0103tor cu borrow checker din Rust? Te-ai uitat la el, ce p\u0103rere ai?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Ei bine, scriu \u00een C de o ve\u0219nicie, cu toate aceste malloc \u0219i free, \u0219i gestionez manual durata de via\u021b\u0103. \u0218ti\u021bi, 90-95% din durata de via\u021b\u0103 gestionat\u0103 manual are aceea\u0219i structur\u0103. \u0218i este foarte, foarte dureros s\u0103 te ocupi de asta manual. Mi-ar pl\u0103cea ca compilatorul s\u0103 spun\u0103 pur \u0219i simplu ce se \u00eent\u00e2mpl\u0103 \u0219i ce ai ob\u021binut prin ac\u021biunile tale. Pentru unele lucruri, borrow checker face asta din cutie. De asemenea, ar trebui s\u0103 extrag\u0103 automat informa\u021bii, s\u0103 \u00een\u021beleag\u0103 totul \u0219i s\u0103 nu m\u0103 \u00eencarce cu faptul de a expune aceast\u0103 \u00een\u021belegere. Ar trebui s\u0103 fac\u0103 cel pu\u021bin o analiz\u0103 local\u0103 a sc\u0103p\u0103rii, \u0219i abia dac\u0103 nu reu\u0219e\u0219te, atunci ar trebui s\u0103 adauge anota\u021bii de tipuri care s\u0103 descrie durata de via\u021b\u0103 \u2013 \u0219i o astfel de schem\u0103 este mult mai complex\u0103 dec\u00e2t borrow checker-ul, sau orice alt checker de memorie existent. Alegerea \u00eentre \u00abtotul e \u00een regul\u0103\u00bb \u0219i \u00abnu am \u00een\u021beles nimic\u00bb \u2014 nu, ar trebui s\u0103 existe ceva mai bun.\u00a0<br \/>\nA\u0219adar, ca o persoan\u0103 care a scris mult cod \u00een C, consider c\u0103 suportul pentru gestionarea automat\u0103 a duratei de via\u021b\u0103 este cel mai important aspect. De asemenea, m-a frustrat foarte mult c\u00e2t de mult\u0103 memorie folose\u0219te Java, iar principala pl\u00e2ngere este c\u0103 \u00een GC (garbage collection). C\u00e2nd aloci memorie \u00een Java, nu prime\u0219ti \u00eenapoi memoria care a fost local\u0103 \u00een ultimul ciclu de GC. \u00cen limbajele cu o gestionare a memoriei mai precis\u0103, acest lucru nu se \u00eent\u00e2mpl\u0103. Dac\u0103 apelezi malloc, prime\u0219ti imediat memoria care, de obicei, a fost utilizat\u0103 recent. De obicei, faci cu memoria diverse lucruri temporare \u0219i o returnezi imediat. \u0218i aceasta revine imediat \u00een pool-ul malloc, iar urm\u0103torul ciclu malloc o extrage din nou. Prin urmare, utilizarea real\u0103 a memoriei se reduce la un set de obiecte active \u00eentr-un anumit moment, plus eventualele scurgeri. \u0218i dac\u0103 nu ai scurgeri \u00eentr-un mod complet inacceptabil, cea mai mare parte a memoriei r\u0103m\u00e2ne \u00een cache-uri \u0219i \u00een procesor, iar aceasta func\u021bioneaz\u0103 rapid. Dar necesit\u0103 mult control manual al memoriei cu malloc \u0219i free, apelate \u00een ordinea \u0219i locul corecte. Rust se poate ocupa de acest lucru corect \u0219i \u00een multe cazuri ofer\u0103 chiar o performan\u021b\u0103 mai mare, deoarece consumul de memorie se restr\u00e2nge doar la calculele curente - spre deosebire de a\u0219teptarea urm\u0103torului ciclu de GC care va elibera memorie. Ca rezultat, am ob\u021binut o modalitate foarte interesant\u0103 de a \u00eembun\u0103t\u0103\u021bi performan\u021ba. \u0218i este destul de puternic\u0103 - \u00een sensul c\u0103 m-am ocupat de astfel de lucruri \u00een prelucrarea datelor pentru fintech, iar aceasta a permis ob\u021binerea unui spor de vitez\u0103 de aproximativ cinci ori. Acesta este un spor considerabil, mai ales \u00eentr-o lume \u00een care procesoarele nu devin mai rapide, iar noi continu\u0103m s\u0103 a\u0219tept\u0103m \u00eembun\u0103t\u0103\u021biri.<\/p>\n<p><\/p>\n<h1 id=\"karera-performans-inzhenera\">Cariera unui inginer de performan\u021b\u0103<\/h1>\n<p><\/p>\n<p><strong>Andrei<\/strong>: De asemenea, a\u0219 vrea s\u0103 \u00eentreb despre carier\u0103 \u00een ansamblu. A\u021bi devenit celebru datorit\u0103 muncii pe JIT \u00een HotSpot \u0219i apoi v-a\u021bi mutat la Azul - \u0219i aceasta este o companie JVM. Dar v-a\u021bi ocupat mai mult de hardware dec\u00e2t de software. Apoi, dintr-o dat\u0103, v-a\u021bi concentrat pe Big Data \u0219i Machine Learning, iar apoi pe detectarea fraudelor. Cum s-a \u00eent\u00e2mplat acest lucru? Acestea sunt domenii foarte diferite de dezvoltare.<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Am practicat programarea de ceva vreme \u0219i am reu\u0219it s\u0103 m\u0103 implic \u00een activit\u0103\u021bi foarte diverse. \u0218i c\u00e2nd oamenii spun: \u201eoh, tu e\u0219ti cel care a f\u0103cut JIT pentru Java!\u201d, este \u00eentotdeauna amuzant. P\u00e2n\u0103 atunci, am lucrat la un clon al PostScript \u2013 limbajul pe care Apple l-a folosit c\u00e2ndva pentru imprimantele sale laser. \u0218i \u00eenainte de aceasta, am realizat o implementare a limbajului Forth. Cred c\u0103 tema comun\u0103 pentru mine este dezvoltarea de instrumente. Toat\u0103 via\u021ba am creat instrumente prin care al\u021bi oameni \u00ee\u0219i scriu programele lejere. Dar am lucrat \u0219i la dezvoltarea sistemelor de operare, drivere, debuggere la nivel de kernel, limbaje pentru dezvoltarea sistemelor de operare, care au \u00eenceput simplu, dar au devenit tot mai complexe. Dar tema principal\u0103 r\u0103m\u00e2ne, totu\u0219i, dezvoltarea instrumentelor. O mare parte din via\u021ba mea a trecut \u00eentre Azul \u0219i Sun, \u0219i a fost despre Java. Dar c\u00e2nd m-am apucat de Big Data \u0219i Machine Learning, mi-am pus din nou p\u0103l\u0103ria de ceremonie \u0219i am spus: \u201eOh, acum avem o problem\u0103 non-trivial\u0103 \u0219i aici se \u00eent\u00e2mpl\u0103 o gr\u0103mad\u0103 de lucruri interesante \u0219i oameni care fac ceva\u201d. Este un traseu excelent de dezvoltare, pe care merit\u0103 s\u0103-l parcurgi. <\/p>\n<p><\/p>\n<p>Da, \u00eemi plac foarte mult calculele distribuite. Primul meu loc de munc\u0103 a fost \u00een studen\u021bie, lucr\u00e2nd cu C, la un proiect publicitar. Erau calcule distribuite pe cipuri Zilog Z80, care colectau date pentru recunoa\u0219terea analogic\u0103 a textului, realizat\u0103 de un adev\u0103rat analizor analogic. A fost un subiect foarte interesant \u0219i complet neobi\u0219nuit. \u00cens\u0103 au fost probleme, o parte din date nu erau recunoscute corect, a\u0219a c\u0103 trebuia s\u0103 scoatem imaginea \u0219i s\u0103 o ar\u0103t\u0103m unei persoane care o citise cu ochii \u0219i ne comunica ce anume era acolo, a\u0219a c\u0103 erau joburi cu date, iar aceste joburi aveau propriul lor limbaj. Era un backend care gestiona totul \u2013 Z80 care lucrau \u00een paralel cu terminale vt100 \u2013 c\u00e2te unul pentru fiecare persoan\u0103, iar modelul de programare paralel\u0103 pe Z80 era utilizat. Un anumit bloc de memorie comun, \u00eemp\u0103r\u021bit de toate Z80 \u00een configura\u021bia tip \u201estea\u201d; bckplane-ul era \u0219i el \u00eemp\u0103r\u021bit, iar jum\u0103tate din RAM era \u00eemp\u0103r\u021bit\u0103 \u00een re\u021bea, iar cealalt\u0103 jum\u0103tate era privat\u0103 sau folosit\u0103 pentru altceva. O sistem\u0103 paralel\u0103 distribuit\u0103 complex\u0103, cu memorie \u00eemp\u0103rt\u0103\u0219it\u0103\u2026 par\u021bial \u00eemp\u0103rt\u0103\u0219it\u0103. C\u00e2nd a fost asta\u2026 deja nu-mi amintesc, undeva prin mijlocul anilor '80. Destul de demult.\u00a0<br \/>\nDa, s\u0103 zicem c\u0103 30 de ani este destul de mult. Sarcinile legate de calculele distribuite exist\u0103 de mult timp, oamenii s-au luptat cu... <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>-clustere. Aceste clustere arat\u0103 ca... De exemplu: exist\u0103 Ethernet \u0219i procesorul t\u0103u x86 rapid este conectat la acest Ethernet, \u0219i acum vrei s\u0103 ob\u021bii memorie partajat\u0103 fals\u0103, pentru c\u0103 nimeni nu putea \u00een acel moment s\u0103 se ocupe de programarea calculelor distribuite, era mult prea complicat \u0219i de aceea a fost creat\u0103 memoria partajat\u0103 fals\u0103 cu protec\u021bia paginilor de memorie pe x86, \u0219i dac\u0103 scriai \u00een aceast\u0103 pagin\u0103, le spuneam celorlalte procesoare c\u0103, dac\u0103 au acces la aceea\u0219i memorie partajat\u0103, trebuie s\u0103 o \u00eencarce de la tine, \u0219i astfel a ap\u0103rut ceva asem\u0103n\u0103tor cu un protocol de suport pentru coeren\u021ba cache-urilor \u0219i software-ul pentru aceasta. O conceptie interesant\u0103. Problema adev\u0103rat\u0103, desigur, era alta. Totul func\u021biona, dar aveai rapid probleme de performan\u021b\u0103, pentru c\u0103 nimeni nu \u00een\u021belegea modelul de performan\u021b\u0103 la un nivel suficient de bun \u2013 care erau modelele de acces la memorie, cum s\u0103 faci astfel \u00eenc\u00e2t nodurile s\u0103 nu se pinguiasc\u0103 reciproc la nesf\u00e2r\u0219it, \u0219i a\u0219a mai departe. <\/p>\n<p><\/p>\n<p>La H2O am avut aceast\u0103 idee: dezvoltatorii \u00een\u0219i\u0219i sunt responsabili pentru a determina unde se afl\u0103 paralelismul \u0219i unde nu. Am conceput un model de codare astfel \u00eenc\u00e2t s\u0103 devin\u0103 u\u0219or \u0219i simplu s\u0103 scriu cod de \u00eenalt\u0103 performan\u021b\u0103. \u00cen schimb, s\u0103 scrii cod care ruleaz\u0103 \u00eencet este complicat, iar acesta va ar\u0103ta prost. Trebuie s\u0103 te str\u0103duie\u0219ti serios pentru a scrie cod lent, va trebui s\u0103 folose\u0219ti metode neobi\u0219nuite. Codul care \u00eencetine\u0219te este vizibil de la prima privire. Ca urmare, de obicei se scrie cod care func\u021bioneaz\u0103 rapid, dar trebuie s\u0103 te descurci cu ce s\u0103 faci \u00een cazul memoriei partajate. Toate acestea sunt legate de mari matrice, iar comportamentul acestora seam\u0103n\u0103 cu matricele mari nevolatibile din Java paralel. G\u00e2nde\u0219te-te c\u0103 dou\u0103 fire scriu \u00eentr-o matrice paralel\u0103, unul dintre ele c\u00e2\u0219tig\u0103, iar cel\u0103lalt, \u00een mod corespunz\u0103tor, pierde, \u0219i nu \u0219tii care dintre ele este care. Dac\u0103 nu sunt volatibile, ordinea poate fi oricum \u2013 \u0219i asta func\u021bioneaz\u0103 cu adev\u0103rat bine. Oamenii chiar se \u00eengrijesc de ordinea opera\u021biunilor, plaseaz\u0103 corect volatile \u0219i \u00een locurile potrivite se a\u0219teapt\u0103 la probleme de performan\u021b\u0103 legate de memorie. Altfel, ar scrie cod sub form\u0103 de bucle de la 1 la N, unde N sunt c\u00e2teva trilioane, sper\u00e2nd c\u0103 toate cazurile complexe vor deveni automat paralele \u2013 \u0219i acolo nu func\u021bioneaz\u0103. Dar \u00een H2O, aceasta nu este Java \u0219i nici Scala, o po\u021bi considera \u201eJava minus minus\u201d, dac\u0103 dore\u0219ti. Este un stil de programare foarte clar \u0219i seam\u0103n\u0103 cu scrierea codului simplu \u00een C sau Java cu bucle \u0219i matrice. Dar \u00een acela\u0219i timp, memoria poate fi procesat\u0103 \u00een terabyte. \u00cenc\u0103 folosesc H2O. Din c\u00e2nd \u00een c\u00e2nd, o folosesc \u00een diferite proiecte \u2013 \u0219i este \u00een continuare cel mai rapid lucru, de zeci de ori superior competitorilor. Dac\u0103 faci Big Data cu date columnare, este foarte greu s\u0103 dep\u0103\u0219e\u0219ti H2O.<\/p>\n<p><\/p>\n<h1 id=\"tehnicheskie-chellenzhi\">Provoc\u0103rile tehnice<\/h1>\n<p><\/p>\n<p><strong>Andrei<\/strong>: Care a fost cea mai mare provocare din \u00eentreaga ta carier\u0103?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Discut\u0103m despre partea tehnic\u0103 sau despre cea non-tehnic\u0103 a \u00eentreb\u0103rii? A\u0219 spune c\u0103 cele mai mari provoc\u0103ri sunt cele non-tehnice.\u00a0<br \/>\n\u00cen ceea ce prive\u0219te provoc\u0103rile tehnice, le-am \u00eenvins. Nu \u0219tiu care a fost cea mai mare, dar au fost c\u00e2teva destul de interesante, la care a trebuit s\u0103 lucrez mult timp \u0219i s\u0103 fac o mul\u021bime de efort mental. C\u00e2nd am venit la Sun, eram convins c\u0103 voi face un compilator rapid, dar o mul\u021bime de seniori mi-au spus c\u0103 nu voi reu\u0219i niciodat\u0103. Dar am mers pe acest drum, am scris un compilator p\u00e2n\u0103 la alocarea registrelor, \u0219i a fost destul de rapid. Era la fel de rapid ca un C1 modern, dar atunci alocarea era mult mai lent\u0103, \u0219i privind \u00eenapoi \u2013 aceasta a fost o problem\u0103 a unei structuri de date mari. Aveam nevoie de ea pentru a scrie un alocator grafic de registre \u0219i nu \u00een\u021belegeam dilema dintre expresivitatea codului \u0219i vitez\u0103, care exista \u00een acea epoc\u0103 \u0219i era foarte important\u0103. S-a dovedit c\u0103 structura de date dep\u0103\u0219e\u0219te de obicei dimensiunea cache-ului pe x86-urile de atunci \u0219i, prin urmare, dac\u0103 la \u00eenceput presupuneam c\u0103 alocarea registrelor va consuma 5-10 procente din tot timpul de jitare, \u00een realitate s-a transformat \u00een 50%. <\/p>\n<p><\/p>\n<p>Timpul a trecut, compilatorul devenea din ce \u00een ce mai clar \u0219i performant, a \u00eencetat s\u0103 genereze cod groaznic \u00een tot mai multe cazuri, iar performan\u021ba a \u00eenceput s\u0103 semene mai mult cu ceea ce produce un compilator C. Dac\u0103, desigur, nu scrii ceva necorespunz\u0103tor, pe care nici m\u0103car C nu-l accelereaz\u0103. Dac\u0103 scrii cod ca \u00een C, ob\u021bii performan\u021b\u0103 similar\u0103 cu C \u00een mai multe cazuri. \u0218i pe m\u0103sur\u0103 ce mergeam mai departe, codul devenea tot mai frecvent asimptotic la nivelul C, alocarea registrelor a \u00eenceput s\u0103 semene cu ceva complet... indiferent dac\u0103 codul t\u0103u ruleaz\u0103 rapid sau lent. Am continuat s\u0103 lucrez la alocator, astfel \u00eenc\u00e2t s\u0103 fac\u0103 aloc\u0103ri mai bune. A devenit din ce \u00een ce mai lent, dar oferea din ce \u00een ce mai mult\u0103 performan\u021b\u0103 \u00een cazurile \u00een care nimeni altcineva nu reu\u0219ea. Puteam s\u0103 intru \u00een alocarea registrelor, s\u0103 \u00eengrop acolo o lun\u0103 de munc\u0103, \u0219i brusc tot codul \u00eencepea s\u0103 ruleze cu 5% mai repede. Se \u00eent\u00e2mpla iar \u0219i iar \u0219i alocarea registrelor a devenit ceva de genul unei opere de art\u0103 \u2013 to\u021bi o iubeau sau o urau, iar oamenii din academie puneau \u00eentreb\u0103ri despre \u201ede ce se face totul \u00een acest mod\u201d, de ce nu <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Register_allocation#Linear_Scan\">scanare liniar\u0103<\/a><\/noindex>, \u0219i care este diferen\u021ba. R\u0103spunsul este acela\u0219i: un aloc\u0103tor bazat pe colorarea grafului plus o gestionare foarte atent\u0103 a codului tampon \u00eenseamn\u0103 un instrument de c\u00e2\u0219tig, cea mai bun\u0103 combina\u021bie, pe care nimeni nu o poate \u00eenfrunta. \u0218i aceasta este o chestiune destul de subtil\u0103. Tot ce face compilatorul acolo sunt lucruri bine cunoscute, de\u0219i \u0219i acestea au fost duse la nivel de art\u0103. \u00centotdeauna am f\u0103cut lucruri care ar fi trebuit s\u0103 transforme compilatorul \u00eentr-o capodoper\u0103. Dar nimic din acestea nu a fost ceva extraordinar \u2013 cu excep\u021bia alocatoarelor de registre. Secretul este c\u0103 trebuie s\u0103 se fac\u0103 cu aten\u021bie <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Register_allocation\">t\u0103ia\u021bi<\/a><\/noindex> sub sarcin\u0103 \u0219i, dac\u0103 se \u00eent\u00e2mpl\u0103 acest lucru (pot explica mai \u00een detaliu, dac\u0103 este de interes), \u00eenseamn\u0103 c\u0103 se poate face inline mai agresiv, f\u0103r\u0103 riscul de a dep\u0103\u0219i la \u00eencruci\u0219area graficului de performan\u021b\u0103. \u00cen acele vremuri existau o mul\u021bime de compilatoare cu toate tipurile de accesorii \u0219i trinkets, care aveau alocatoare de registre, dar nimeni nu a mai reu\u0219it asta. <\/p>\n<p><\/p>\n<p>Problema este c\u0103, dac\u0103 adaugi metode care pot fi inlinate, m\u0103rind \u0219i mai mult domeniul inlining-ului, setul de valori utilizate dep\u0103\u0219e\u0219te instantaneu num\u0103rul de registre \u0219i devine necesar s\u0103 faci spilling. Nivelul critic apare de obicei atunci c\u00e2nd alocatorul renun\u021b\u0103, iar un bun candidat pentru spilling valoreaz\u0103 c\u00e2t altul, iar tu \u00eencepi s\u0103 faci spilling pe unele lucruri complet ciudate. Valoarea inlining-ului consta \u00een faptul c\u0103 pierzi o parte din overhead, overhead-ul apelului \u0219i salv\u0103rii; po\u021bi vedea valorile interne \u0219i le po\u021bi optimiza \u00een continuare. Costul inlining-ului este c\u0103 se genereaz\u0103 un num\u0103r mare de valori viabile \u0219i, dac\u0103 alocatorul t\u0103u de registre face spilling de mai multe ori dec\u00e2t este necesar, pierzi imediat. Prin urmare, majoritatea allocatorilor se confrunt\u0103 cu problema c\u0103, atunci c\u00e2nd inlining-ul trece peste o anumit\u0103 limit\u0103, \u00eencepe s\u0103 fac\u0103 spilling pentru tot \u0219i performan\u021ba poate fi redus\u0103 drastic. Cei care implementeaz\u0103 compilatorul adaug\u0103 unele heuristici: de exemplu, pentru a opri inlining-ul, \u00eencep\u00e2nd de la o dimensiune suficient de mare, deoarece aloc\u0103rile vor deteriora totul. Astfel se formeaz\u0103 un punct de inflexiune \u00een graficul performan\u021bei \u2013 faci inlining, faci inlining, performan\u021ba cre\u0219te u\u0219or \u2013 \u0219i apoi bum! \u2013 scade brusc, pentru c\u0103 ai realizat prea mult inlining. A\u0219a a func\u021bionat totul p\u00e2n\u0103 la apari\u021bia Java. Java necesit\u0103 mult mai mult inlining, a\u0219a c\u0103 a trebuit s\u0103 fac alocatorul meu mult mai agresiv pentru a se stabiliza, \u0219i nu a c\u0103dea, iar dac\u0103 ai f\u0103cut prea mult inlining \u2013 el \u00eencepe s\u0103 fac\u0103 spilling, dar apoi totu\u0219i ajunge momentul \u201enu mai este spilling\u201d. Aceasta este o observa\u021bie interesant\u0103 \u0219i a venit la mine dintr-o dat\u0103, nu era evident, dar s-a dovedit a fi bine r\u0103spl\u0103tit\u0103. Am adoptat inlining-ul agresiv \u0219i m-a dus \u00een locuri \u00een care performan\u021ba Java \u0219i C sunt comparabile. Ele sunt \u00eentr-adev\u0103r apropiate \u2013 pot scrie cod \u00een Java care este semnificativ mai rapid dec\u00e2t codul \u00een C \u0219i a\u0219a mai departe, dar \u00een medie, \u00een imaginea de ansamblu, sunt aproximativ comparabile. Cred c\u0103 o parte din aceast\u0103 realizare se datoreaz\u0103 alocatorului de registre, care \u00eemi permite s\u0103 fac inlining la capacitate maxim\u0103. Eu pur \u0219i simplu fac inlining cu tot ceea ce v\u0103d. \u00centrebarea este dac\u0103 alocatorul func\u021bioneaz\u0103 bine, rezult\u00e2nd un cod care func\u021bioneaz\u0103 \u00een mod rezonabil. Acesta a fost un mare provocare: s\u0103 \u00een\u021beleg tot acest lucru \u0219i s\u0103-l fac s\u0103 func\u021bioneze.<\/p>\n<p><\/p>\n<h1 id=\"nemnogo-pro-allokaciyu-registrov-i-mnogoyadernost\">Pu\u021bin despre alocarea registrelor \u0219i multicoeren\u021b\u0103<\/h1>\n<p><\/p>\n<p><strong>Vladimir<\/strong>: Probleme precum alocarea registrelor par a fi un subiect etern f\u0103r\u0103 sf\u00e2r\u0219it. Este interesant dac\u0103 a existat vreodat\u0103 o idee care p\u0103rea promi\u021b\u0103toare, dar care a e\u0219uat \u00een practic\u0103?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Desigur! Alocarea registrelor este un domeniu \u00een care, pentru a rezolva o problem\u0103 NP-complet\u0103, \u00eencerci s\u0103 g\u0103se\u0219ti anumite euristici. \u0218i niciodat\u0103 nu vei putea ob\u021bine o solu\u021bie perfect\u0103, nu-i a\u0219a? Este pur \u0219i simplu imposibil. Uite, compilarea Ahead of Time \u2013 nici aceasta nu func\u021bioneaz\u0103 bine. Vorbim aici despre cazuri medii. Despre performan\u021ba tipic\u0103, a\u0219a c\u0103 po\u021bi s\u0103 te duci \u0219i s\u0103 m\u0103sori ceva ce consideri a fi o performan\u021b\u0103 tipic\u0103 bun\u0103 \u2013 p\u00e2n\u0103 la urm\u0103, tu lucrezi la \u00eembun\u0103t\u0103\u021birea ei! Alocarea registrelor este un subiect dedicat integral performan\u021bei. Odat\u0103 ce ai un prim prototip, care func\u021bioneaz\u0103 \u0219i face ceea ce trebuie, urmeaz\u0103 munca asupra performan\u021bei. Trebuie s\u0103 \u00eenve\u021bi s\u0103 m\u0103sori bine. De ce este important? Dac\u0103 ai date clare, po\u021bi s\u0103 te ui\u021bi la diferite sec\u021biuni \u0219i s\u0103 vezi: aha, asta a ajutat aici, dar acolo a e\u0219uat totul! Apar idei bune, adaugi o nou\u0103 euristic\u0103 \u0219i brusc totul \u00eencepe s\u0103 func\u021bioneze pu\u021bin mai bine \u00een medie. Sau nu \u00eencepe. Am avut o gr\u0103mad\u0103 de cazuri \u00een care ne-am luptat pentru cinci procente de performan\u021b\u0103 care ne-au diferen\u021biat dezvoltarea de alocatorul anterior. \u0218i de fiecare dat\u0103 arat\u0103 astfel: c\u00e2teva c\u00e2teva c\u00e2\u0219tiguri, c\u00e2teva pierderi. Dac\u0103 ai instrumente bune de analiz\u0103 a performan\u021bei, po\u021bi g\u0103si ideile pierdute \u0219i \u00een\u021belege de ce au e\u0219uat. Poate c\u0103 ar trebui s\u0103 l\u0103s\u0103m totul a\u0219a cum este, poate c\u0103 ar trebui s\u0103 ne ocup\u0103m mai serios de ajust\u0103ri fine sau s\u0103 mergem s\u0103 repar\u0103m ceva diferit. Este un \u00eentreg set de lucruri! Am realizat acest hack interesant, dar am nevoie \u0219i de acesta, \u0219i de acesta, \u0219i de acesta \u2013 iar combina\u021bia lor total\u0103 ofer\u0103 anumite \u00eembun\u0103t\u0103\u021biri. Iar solu\u021biile unice pot e\u0219ua. Asta este natura muncii asupra problemelor de performan\u021b\u0103 NP-complete.<\/p>\n<p><\/p>\n<p><strong>Vladimir<\/strong>: Se pare c\u0103 lucruri precum colorarea \u00een alocatoare sunt o problem\u0103 deja rezolvat\u0103. Ei bine, pentru voi pare rezolvat\u0103, judec\u00e2nd dup\u0103 ceea ce povesti\u021bi, a\u0219a c\u0103 merit\u0103 s\u0103...<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Nu este rezolvat\u0103 \u00een sine. Tu trebuie s\u0103 o transformi \u00een \u201erezolvat\u0103\u201d. Exist\u0103 sarcini complexe \u0219i trebuie abordate. Odat\u0103 ce acest lucru este realizat, vine timpul pentru a lucra la performan\u021b\u0103. Trebuie s\u0103 abordezi aceast\u0103 munc\u0103 \u00een mod corespunz\u0103tor \u2013 s\u0103 faci benchmark-uri, s\u0103 colectezi metrice, s\u0103 explici situa\u021biile \u00een care, c\u00e2nd te \u00eentorci la o versiune anterioar\u0103, vechiul t\u0103u hack \u00eencepe din nou s\u0103 func\u021bioneze (sau invers, s\u0103 nu mai func\u021bioneze). \u0218i nu te abate p\u00e2n\u0103 nu ob\u021bii un rezultat. A\u0219a cum am mai spus, ideile grozave care nu au func\u021bionat, dar \u00een domeniul aloc\u0103rii registrelor sunt practic nelimitate. Po\u021bi, de exemplu, s\u0103 cite\u0219ti publica\u021bii \u0219tiin\u021bifice. De\u0219i acum acest domeniu a \u00eenceput s\u0103 progreseze mult mai lent \u0219i a devenit mai clar dec\u00e2t \u00een vremurile sale de \u00eenceput. Totu\u0219i, \u00een acest domeniu lucreaz\u0103 o infinitate \u00eentreag\u0103 de oameni \u0219i toate ideile lor merit\u0103 \u00eencercate, toate a\u0219teapt\u0103 momentul lor. \u0218i nu po\u021bi spune c\u00e2t de bune sunt, dac\u0103 nu le \u00eencerci. C\u00e2t de bine se integreaz\u0103 totul cu restul \u00een aloc\u0103torul t\u0103u, c\u0103ci aloc\u0103torul face o mul\u021bime de lucruri, \u0219i unele idei din aloc\u0103torul t\u0103u specific nu vor func\u021biona, dar \u00een alt aloc\u0103tor \u2013 cu u\u0219urin\u021b\u0103. Principala modalitate de a \u00eenvinge pentru un aloc\u0103tor este de a scoate lucrurile lente din calea principal\u0103 \u0219i a for\u021ba divizarea pe marginile c\u0103ilor lente. A\u0219adar, dac\u0103 vrei s\u0103 lansezi GC, s\u0103 alegi calea lent\u0103, s\u0103 te deoptimizzi, s\u0103 arunci excep\u021bii, tot \u00een acest spirit \u2013 \u0219tii c\u0103 aceste lucruri sunt relativ rare. \u0218i chiar sunt rare, am verificat. Faci munc\u0103 suplimentar\u0103 \u0219i datorit\u0103 acestui fapt dispar numeroase limit\u0103ri pe aceste c\u0103i lente, dar acesta nu este foarte important, deoarece sunt lente \u0219i sunt frecventate rar. De exemplu, un pointer nul \u2013 acesta nu se \u00eent\u00e2mpl\u0103 niciodat\u0103, nu-i a\u0219a? Trebuie s\u0103 ai mai multe c\u0103i pentru lucruri diferite, dar nu trebuie s\u0103 se suprapun\u0103 \u00een calea principal\u0103.\u00a0<\/p>\n<p><\/p>\n<p><strong>Vladimir<\/strong>: Ce p\u0103rere ai despre multicores, c\u00e2nd sunt mii de nuclee deodat\u0103? Este un lucru util?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>:Succesul GPU arat\u0103 c\u0103 este destul de util!<\/p>\n<p><\/p>\n<p><strong>Vladimir<\/strong>:Sunt destul de specializate. Dar ce zici de procesoarele de uz general?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Ei bine, acesta a fost modelul de afaceri Azul. R\u0103spunsul a venit \u00eenc\u0103 dintr-o epoc\u0103 \u00een care oamenii iubeau foarte mult performan\u021ba predictibil\u0103. Atunci era destul de dificil s\u0103 scrii cod paralel. Modelul de codare H2O se scaleaz\u0103 bine, dar nu este un model de uz general. Poate doar u\u0219or mai general dec\u00e2t utilizarea GPU-ului. Vorbim despre complexitatea dezvolt\u0103rii unei astfel de solu\u021bii sau despre complexitatea utiliz\u0103rii acesteia? De exemplu, o lec\u021bie interesant\u0103 pe care mi-a oferit-o Azul, destul de neobi\u0219nuit\u0103: cache-urile mici sunt \u00een regul\u0103.\u00a0<\/p>\n<p><\/p>\n<h1 id=\"samyy-bolshoy-chellenzh-v-zhizni\">Cea mai mare provocare din via\u021ba mea<\/h1>\n<p><\/p>\n<p><strong>Vladimir<\/strong>: Ce zici de provoc\u0103rile non-tehnice?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Cea mai mare provocare a fost s\u0103 nu fiu\u2026 bun \u0219i pl\u0103cut cu oamenii. Ca urmare, m-am aflat constant \u00een situa\u021bii extrem de conflictuale. Cele \u00een care \u0219tiam c\u0103 totul merge prost, dar nu \u0219tiam cum s\u0103 \u00eenaintesc \u00een rezolvarea acestor probleme \u0219i nu am reu\u0219it s\u0103 fac fa\u021b\u0103 lor. Multe probleme de lung\u0103 durat\u0103, care au durat zeci de ani, au ap\u0103rut tocmai \u00een acest fel. Faptul c\u0103 \u00een Java exist\u0103 compilatoare C1 \u0219i C2 este o consecin\u021b\u0103 direct\u0103 a acestui lucru. De asemenea, faptul c\u0103 \u00een Java, timp de un deceniu, nu a existat compilare multi-nivel este tot o consecin\u021b\u0103 direct\u0103. Este evident c\u0103 aveam nevoie de un astfel de sistem, dar nu este clar de ce nu a existat. Am avut probleme cu un inginer\u2026 sau cu un grup de ingineri. Cu mult timp \u00een urm\u0103, c\u00e2nd am \u00eenceput s\u0103 lucrez la Sun, eram\u2026 Bine, nu doar atunci, am avut mereu o opinie proprie despre tot. \u0218i am considerat c\u0103 este o adev\u0103r absolut c\u0103 se poate lua aceast\u0103 adev\u0103r \u0219i spune simplu. Mai ales c\u0103 de cele mai multe ori aveam dreptate \u00een mod \u0219ocant. Iar dac\u0103 \u00ee\u021bi displace aceast\u0103 abordare\u2026 mai ales dac\u0103 te \u00een\u0219eli evident \u0219i faci prostii\u2026 \u00cen general, pu\u021bini oameni puteau suporta o astfel de form\u0103 de comunicare cu toleran\u021b\u0103. De\u0219i unii puteau, de exemplu, eu. Mi-am construit \u00eentreaga via\u021b\u0103 pe principii meritocratice. Dac\u0103 \u00eemi ar\u0103\u021bi ceva gre\u0219it, m\u0103 voi \u00eentoarce imediat \u0219i voi spune: ai spus o prostie. Totu\u0219i, desigur, m\u0103 voi scuza \u0219i voi face toate celelalte ac\u021biuni corecte. Pe de alt\u0103 parte, am fost \u0219ocant de corect un procent \u0219ocant de mare din timp. \u0218i asta nu func\u021bioneaz\u0103 prea bine \u00een rela\u021biile cu oamenii. Nu m\u0103 str\u0103duiesc s\u0103 fiu dr\u0103gu\u021b, ci pun problema pe masa discu\u021biei. \u201eAsta nu va func\u021biona niciodat\u0103, pentru c\u0103 unu, doi \u0219i trei\u201d. \u0218i ei sunt: \u201eOh!\u201d. Au fost \u0219i alte consecin\u021be, pe care cel mai bine este probabil s\u0103 le ocolim: de exemplu, cele care au dus la divor\u021bul de so\u021bie \u0219i la zece ani de depresie dup\u0103 aceea.<\/p>\n<p><\/p>\n<p>Provocarea este lupta cu percep\u021bia oamenilor despre ceea ce po\u021bi sau nu po\u021bi face, despre ceea ce este important \u0219i ceea ce nu este. Au fost multe provoc\u0103ri legate de stilul de codare. \u00cenc\u0103 mai scriu mult cod \u0219i \u00een acele vremuri a trebuit s\u0103 \u00eencetinesc, deoarece f\u0103ceam prea multe sarcini paralele \u0219i le f\u0103ceam prost, \u00een loc s\u0103 m\u0103 concentrez pe una singur\u0103. Privind \u00eenapoi, am scris jum\u0103tate din codul echipei Java JIT, echipa C2. Urm\u0103torul coder \u00een vitez\u0103 scria de dou\u0103 ori mai \u00eencet, iar urm\u0103torul \u2013 \u0219i mai \u00eencet, \u0219i a fost o c\u0103dere exponen\u021bial\u0103. Persoana a \u0219aptea din aceast\u0103 serie a fost foarte, foarte lent\u0103 \u2013 a\u0219a se \u00eent\u00e2mpl\u0103 mereu! Am trecut printr-un morman de cod. M-am uitat cine ce scrie, f\u0103r\u0103 excep\u021bii, m-am concentrat pe codul lor, am revizuit pe fiecare dintre ei \u0219i \u00eenc\u0103 scriam mai mult dec\u00e2t oricare dintre ei. Cu oamenii, aceast\u0103 abordare nu func\u021bioneaz\u0103 prea bine. Unii nu \u00eei place acest lucru. \u0218i c\u00e2nd nu pot face fa\u021b\u0103, \u00eencep diverse reclama\u021bii. De exemplu, mi s-a spus odat\u0103 s\u0103 \u00eencetez s\u0103 scriu cod, deoarece scriu prea mult cod, iar asta pune \u00een pericol echipa, \u0219i pentru mine toate acestea p\u0103reau o glum\u0103: omule, dac\u0103 \u00eentreaga echip\u0103 restant\u0103 dispare \u0219i eu continui s\u0103 scriu cod, vei pierde doar jum\u0103tate din echip\u0103. Pe de alt\u0103 parte, dac\u0103 continui s\u0103 scriu cod \u0219i tu pierzi jum\u0103tate din echip\u0103 \u2013 asta sun\u0103 ca un management foarte prost. Nu m-am g\u00e2ndit prea mult la asta, nu am vorbit niciodat\u0103 despre asta, dar totu\u0219i a fost undeva \u00een mintea mea. O idee \u00eemi rotea \u00een col\u021burile con\u0219tiin\u021bei: \u201eChiar v\u0103 lua\u021bi \u00een serios?\u201d. A\u0219a c\u0103, cea mai mare problem\u0103 am fost eu \u0219i rela\u021biile mele cu oamenii. Acum m\u0103 \u00een\u021beleg mult mai bine, am fost mult timp team lead la programatori \u0219i acum le spun direct oamenilor: \u0219ti\u021bi, sunt a\u0219a cum sunt, \u0219i va trebui s\u0103 face\u021bi fa\u021b\u0103 \u2013 nu-i nimic c\u0103 stau aici? \u0218i c\u00e2nd au avut succes cu asta, totul a \u00eenceput s\u0103 func\u021bioneze. De fapt, nu sunt nici r\u0103u, nici bun, nu am inten\u021bii rele sau aspira\u021bii egoiste, este pur \u0219i simplu esen\u021ba mea, \u0219i trebuie s\u0103 tr\u0103im cu asta.<\/p>\n<p><\/p>\n<p><strong>Andrei<\/strong>: Recent, toat\u0103 lumea a \u00eenceput s\u0103 vorbeasc\u0103 despre autocuno\u0219tin\u021b\u0103 pentru introver\u021bi \u0219i, \u00een general, despre abilit\u0103\u021bile soft. Ce se poate spune despre asta?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Da, a fost o \u00een\u021belegere \u0219i o lec\u021bie pe care am extrasa din divor\u021bul cu so\u021bia. Ceea ce am \u00eenv\u0103\u021bat din divor\u021b este o \u00een\u021belegere de sine. Astfel, am \u00eenceput s\u0103 \u00een\u021beleg al\u021bi oameni. S\u0103 \u00een\u021beleg cum func\u021bioneaz\u0103 aceast\u0103 interac\u021biune. A dus la descoperiri una dup\u0103 alta. A ap\u0103rut con\u0219tientizarea a cine sunt \u0219i ce reprezint. Ce fac: fie c\u0103 sunt preocupat de sarcini, fie c\u0103 evit conflictele, sau altceva \u2013 \u0219i acest nivel de con\u0219tientizare de sine m\u0103 ajut\u0103 cu adev\u0103rat s\u0103 m\u0103 men\u021bin \u00een fr\u00e2u. Dup\u0103 aceea, totul devine mai simplu. O chestiune pe care am descoperit-o nu doar la mine, ci \u0219i la al\u021bi programatori \u2013 imposibilitatea de a verbaliza g\u00e2ndurile atunci c\u00e2nd te afli \u00eentr-o stare de stres emo\u021bional. De exemplu, stai \u0219i codifici, e\u0219ti \u00eentr-o stare de flux, \u0219i apoi cineva vine \u0219i \u00eencepe s\u0103 strige disperat c\u0103 ceva s-a stricat, \u0219i c\u0103 acum vor fi luate m\u0103suri extreme. \u0218i nu po\u021bi s\u0103 spui un cuv\u00e2nt pentru c\u0103 te g\u0103se\u0219ti \u00eentr-o stare de stres emo\u021bional. Cuno\u0219tin\u021bele acumulate te ajut\u0103 s\u0103 te preg\u0103te\u0219ti pentru acel moment, s\u0103-l tr\u0103ie\u0219ti \u0219i s\u0103 treci la un plan de retragere, dup\u0103 care po\u021bi face ceva. A\u0219adar, da, c\u00e2nd \u00eencepi s\u0103 con\u0219tientizezi cum func\u021bioneaz\u0103 totul \u2013 este un eveniment cu adev\u0103rat semnificativ care \u00ee\u021bi poate schimba via\u021ba.\u00a0<br \/>\nEu personal nu am reu\u0219it s\u0103 g\u0103sesc cuvintele potrivite, dar am re\u021binut secven\u021ba ac\u021biunilor. Esen\u021ba este c\u0103 aceast\u0103 reac\u021bie este la fel de fizic\u0103, pe c\u00e2t este \u0219i verbal\u0103, \u0219i ai nevoie de spa\u021biu. Un astfel de spa\u021biu, \u00een sens zen. Exact asta trebuie explicat, iar apoi imediat s\u0103 te retragi \u2013 pur \u0219i simplu s\u0103 te retragi fizic. C\u00e2nd tac, pot procesa situa\u021bia din punct de vedere emo\u021bional. Pe m\u0103sur\u0103 ce adrenalina ajunge la creier, te comut\u0103 \u00een modul \u201efugi sau lupt\u0103\u201d, nu mai po\u021bi s\u0103 vorbe\u0219ti, nu \u2013 acum e\u0219ti un idiot, un inginer de b\u0103taie, incapabil s\u0103 oferi un r\u0103spuns demn sau s\u0103 opre\u0219ti atacul, iar atacatorul poate lovi liber din nou \u0219i din nou. Trebuie, mai \u00eent\u00e2i, s\u0103 devii din nou ceea ce erai, s\u0103 rec\u00e2\u0219tigi controlul, s\u0103 ie\u0219i din modul \u201efugi sau lupt\u0103\u201d. <\/p>\n<p><\/p>\n<p>\u0218i pentru asta este necesar un spa\u021biu verbal. Pur \u0219i simplu un spa\u021biu liber. Dac\u0103 totu\u0219i trebuie s\u0103 spui ceva, po\u021bi pur \u0219i simplu s\u0103 declari asta \u0219i apoi s\u0103 mergi \u0219i s\u0103 \u00ee\u021bi g\u0103se\u0219ti \u201espa\u021biul\u201d: s\u0103 te plimbi prin parc, s\u0103 te \u00eenchizi \u00een du\u0219 \u2013 nu conteaz\u0103. Important este s\u0103 te deconectezi temporar de la situa\u021bia respectiv\u0103. Odat\u0103 ce reu\u0219e\u0219ti s\u0103 te deconectezi m\u0103car pentru c\u00e2teva secunde, controlul revine, \u00eencepi s\u0103 g\u00e2nde\u0219ti clar. \u201eBine, nu sunt vreun idiot, nu fac lucruri stupide, sunt o persoan\u0103 destul de util\u0103.\u201d Odat\u0103 ce ai reu\u0219it s\u0103 te convingi pe tine \u00eens\u0103\u021bi, este timpul s\u0103 treci la urm\u0103toarea etap\u0103: s\u0103 \u00een\u021belegi ce s-a \u00eent\u00e2mplat. Ai fost atacat, atacul a venit dintr-o direc\u021bie nea\u0219teptat\u0103, a fost o ambuscad\u0103 nedreapt\u0103 \u0219i tic\u0103loas\u0103. Asta e r\u0103u. Pasul urm\u0103tor este s\u0103 \u00een\u021belegi de ce atacatorul a sim\u021bit nevoia s\u0103 fac\u0103 asta. Chiar, de ce? Poate pentru c\u0103 el \u00eensu\u0219i este furios? De ce e furios? De exemplu, pentru c\u0103 a gre\u0219it \u0219i nu poate accepta responsabilitatea? A\u0219a trebuie s\u0103 abordezi \u00eentreaga situa\u021bie cu delicate\u021be. Dar pentru asta ai nevoie de un spa\u021biu de manevr\u0103, un spa\u021biu verbal. Primul pas este s\u0103 \u00eentrerupi contactul verbal. S\u0103 te \u00eendep\u0103rtezi de discu\u021bia verbal\u0103. S\u0103 anulezi asta, s\u0103 pleci c\u00e2t mai repede. Dac\u0103 este o conversa\u021bie telefonic\u0103 \u2013 pur \u0219i simplu \u00eenchide telefonul \u2013 asta este o abilitate pe care am \u00eenv\u0103\u021bat-o din comunicarea cu fosta mea so\u021bie. Dac\u0103 discu\u021bia nu duce la nimic bun, pur \u0219i simplu spune \u201ela revedere\u201d \u0219i \u00eenchide. De cealalt\u0103 parte a telefonului: \u201ebla-bla-bla\u201d, tu r\u0103spunzi: \u201eaha, pa!\u201d \u0219i \u00eenchizi. Pur \u0219i simplu \u00eentrerupi conversa\u021bia. Cinci minute mai t\u00e2rziu, c\u00e2nd \u00ee\u021bi revine capacitatea de a g\u00e2ndi clar, te calmezi pu\u021bin, devine posibil s\u0103 reflectezi asupra a ceea ce s-a \u00eent\u00e2mplat \u0219i ce va urma. \u0218i s\u0103 \u00eencepi s\u0103 formulezi un r\u0103spuns bine g\u00e2ndit, nu doar s\u0103 reac\u021bionezi din emo\u021bii. Pentru mine, o revela\u021bie \u00een auto-con\u0219tientizare a fost tocmai aceea c\u0103, \u00een cazul stresului emo\u021bional, nu pot vorbi. S\u0103 ie\u0219i din aceast\u0103 stare, s\u0103 g\u00e2nde\u0219ti \u0219i s\u0103 planifici cum s\u0103 r\u0103spunzi \u0219i s\u0103 compensezi problemele \u2013 acestea sunt pa\u0219ii corec\u021bi atunci c\u00e2nd nu po\u021bi vorbi. Cel mai simplu mod este s\u0103 fugi de situa\u021bia care genereaz\u0103 stres emo\u021bional \u0219i pur \u0219i simplu s\u0103 \u00eencetezi s\u0103 mai participi \u00een acel stres. Dup\u0103 aceea, dob\u00e2nde\u0219ti capacitatea de a g\u00e2ndi, c\u00e2nd po\u021bi g\u00e2ndi, apare posibilitatea de a vorbi \u0219i a\u0219a mai departe.<\/p>\n<p><\/p>\n<p>\u00centre timp, avocatul p\u0103r\u021bii adverse \u00eencearc\u0103 s\u0103 fac\u0103 asta cu tine \u2013 acum este clar de ce. Pentru c\u0103 el are posibilitatea de a te suprima p\u00e2n\u0103 \u00een a\u0219a m\u0103sur\u0103 \u00eenc\u00e2t s\u0103 nu po\u021bi nici m\u0103car s\u0103-\u021bi spui numele, de exemplu. \u00cen cel mai direct sens, nu vei putea vorbi. Dac\u0103 \u021bi se \u00eent\u00e2mpl\u0103 acest lucru \u0219i \u0219tii c\u0103 te vei afla \u00eentr-un loc unde se desf\u0103\u0219oar\u0103 b\u0103t\u0103lii verbale, \u00eentr-un loc precum instan\u021ba, po\u021bi veni cu avocatul t\u0103u. Avocatul se va interpune \u00een ap\u0103rarea ta \u0219i va opri atacul verbal, \u0219i va face asta \u00een mod legal, iar \u021bie \u021bi se va reda spa\u021biul zen pierdut. De exemplu, a trebuit s\u0103 sun de c\u00e2teva ori familia, iar judec\u0103torul a fost destul de prietenos cu asta, dar avocatul p\u0103r\u021bii adverse a strigat \u0219i a strigat la mine, nu am putut s\u0103 intervin cu nicio vorb\u0103. \u00cen astfel de cazuri, cel mai bine pentru mine func\u021bioneaz\u0103 folosirea unui mediator. Mediatorul opre\u0219te toat\u0103 aceast\u0103 presiune care curge peste tine \u00eentr-un flux continuu, redescoperi spa\u021biul zen necesar, iar \u00eempreun\u0103 cu el revine capacitatea de a vorbi. Este un domeniu \u00eentreg de cuno\u0219tin\u021be \u00een care trebuie s\u0103 \u00eenve\u021bi multe, s\u0103 descoperi multe \u00een tine, iar toate acestea se transform\u0103 \u00een solu\u021bii strategice de nivel \u00eenalt, diferite pentru diferite persoane. Unii nu au problemele descrise mai sus, de obicei, nu au oameni care se ocup\u0103 profesional de v\u00e2nz\u0103ri. To\u021bi ace\u0219ti oameni care \u00ee\u0219i c\u00e2\u0219tig\u0103 existen\u021ba din cuvinte \u2013 c\u00e2nt\u0103re\u021bi celebri, poe\u021bi, lideri religio\u0219i \u0219i politicieni, au \u00eentotdeauna ceva de spus. Ei nu au astfel de probleme, dar eu le am.<\/p>\n<p><\/p>\n<p><strong>Andrei<\/strong>: A fost\u2026 nea\u0219teptat. Perfect, am discutat destul de mult \u0219i e timpul s\u0103 \u00eencheiem acest interviu. Ne vom \u00eent\u00e2lni cu siguran\u021b\u0103 la conferin\u021b\u0103 \u0219i vom putea continua acest dialog. Ne vedem la Hydra!<\/p>\n<p><\/p>\n<blockquote><p>Po\u021bi continua discu\u021bia cu Cliff la conferin\u021ba Hydra 2019, care va avea loc pe 11-12 iulie 2019 \u00een Sankt Petersburg. El va veni cu o prezentare <noindex><a rel=\"nofollow\" href=\"https:\/\/hydraconf.com\/2019\/talks\/2jix5mst7iduyp9linqhfj\/?utm_source=habr&amp;utm_medium=45871\">\u201eExperien\u021ba Azul Hardware Transactional Memory\u201d<\/a><\/noindex>. Biletele pot fi achizi\u021bionate <noindex><a rel=\"nofollow\" href=\"https:\/\/hydraconf.ru\/?utm_source=habr&amp;utm_medium=458718\">de pe site-ul oficial<\/a><\/noindex>.<\/p><\/blockquote>\n<p>Sursa: <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.2.1 - 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\/ro\/blog\/administrirovanie\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"ro_RO\" \/>\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\/ro\/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\udd47Un interviu amplu cu Cliff Click \u2014 p\u0103rintele JIT-ului \u00een Java | ProHoster","description":"Cliff Click \u2014.","canonical_url":"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"ro_RO","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\/ro\/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\/ro\/wp-json\/wp\/v2\/posts\/35851","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/comments?post=35851"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/35851\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media?parent=35851"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/categories?post=35851"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/tags?post=35851"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}