{"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\/pl\/blog\/administrirovanie\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java","title":{"rendered":"Wielki wywiad z Cliffem Clickiem \u2014 ojcem JIT kompilacji w Javie","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Wielki wywiad z Cliffem Clickiem \u2014 ojcem JIT kompilacji w Javie\" 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 improvement), founder and co-founder of several startups (including Rocket Realtime School, Neurensic, and H2O.ai) with several successful exits. Cliff wrote his first compiler at the age of 15 (Pascal for TRS Z-80)! He is best known for his work on C2 in Java (the Sea of Nodes IR). This compiler showed the world that JIT can produce quality code, which became one of the factors in establishing Java as one of the main modern software platforms. Later, Cliff helped Azul Systems build an 864-core mainframe with software written purely in Java, which supported 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 hub post 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 refactorings<\/li>\n<li>Cost model<\/li>\n<li>Learning low-level optimizations<\/li>\n<li>Practical examples of performance improvements<\/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 of 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 various projects: testing a distributed NewSQL database at Yandex, a cloud detection system at Kaspersky Lab, a multiplayer game at Mail.ru, and a currency pricing service at Deutsche Bank. He is interested in testing large-scale backend and distributed systems.<\/li>\n<li><strong>W\u0142adimir Sitnikow<\/strong> from Netcracker. He has been working for ten years on performance and scalability of NetCracker OS \u2014 software used by telecom operators to automate network management processes and network equipment. He is passionate about Java and Oracle Database performance issues. An author of more than 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, Java, and performance work in general, are you not?\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 the choice between high-level and low-level optimizations like working at the CPU level?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: To jest proste. Najszybszy kod to ten, kt\u00f3ry nigdy nie jest uruchamiany. Dlatego zawsze nale\u017cy zaczyna\u0107 od wysokiego poziomu, pracowa\u0107 nad algorytmami. Lepsza notacja O pokona gorsz\u0105 notacj\u0119 O, chyba \u017ce interweniuj\u0105 jakie\u015b wystarczaj\u0105co du\u017ce sta\u0142e. Rzeczy niskiego poziomu przychodz\u0105 na samym ko\u0144cu. Zwykle, je\u015bli zoptymalizujesz pozosta\u0142\u0105 cz\u0119\u015b\u0107 stosu wystarczaj\u0105co dobrze, a nadal zostaje co\u015b interesuj\u0105cego \u2013 to jest w\u0142a\u015bnie niski poziom. Ale jak zacz\u0105\u0107 od wysokiego poziomu? Jak dowiedzie\u0107 si\u0119, \u017ce wystarczaj\u0105co dobrze pracowano na wysokim poziomie? C\u00f3\u017c... nie ma gotowych recept. Trzeba zrozumie\u0107 problem, zdecydowa\u0107, co zamierzasz zrobi\u0107 (aby nie podejmowa\u0107 niepotrzebnych w p\u00f3\u017aniejszym czasie krok\u00f3w) i wtedy mo\u017cna ju\u017c si\u0119gn\u0105\u0107 po profiler, kt\u00f3ry mo\u017ce powiedzie\u0107 co\u015b u\u017cytecznego. W pewnym momencie sam rozumiesz, \u017ce pozby\u0142e\u015b si\u0119 niepotrzebnych rzeczy i nasta\u0142 czas, aby zaj\u0105\u0107 si\u0119 drobnym dostrajaniem niskiego poziomu. To z pewno\u015bci\u0105 jest szczeg\u00f3lnym rodzajem sztuki. Wiele os\u00f3b robi niepotrzebne rzeczy, ale porusza si\u0119 tak szybko, \u017ce nie maj\u0105 czasu, aby dba\u0107 o wydajno\u015b\u0107. Ale to do momentu, gdy problem staje si\u0119 krytyczny. Zwykle 99% czasu nikogo nie interesuje, czym si\u0119 zajmuj\u0119, a\u017c do momentu, gdy na krytycznej drodze pojawi si\u0119 wa\u017cna sprawa, kt\u00f3ra kogo\u015b obchodzi. I wtedy wszyscy zaczynaj\u0105 dopytywa\u0107, dlaczego to od samego pocz\u0105tku nie dzia\u0142a\u0142o idealnie. Generalnie zawsze jest co\u015b do poprawy w wydajno\u015bci. Ale 99% czasu nie masz wskaz\u00f3wek! Po prostu pr\u00f3bujesz sprawi\u0107, aby co\u015b dzia\u0142a\u0142o, a w trakcie tego dowiadujesz si\u0119, co jest wa\u017cne. Nigdy nie mo\u017cna z g\u00f3ry wiedzie\u0107, \u017ce ten kawa\u0142ek trzeba zrobi\u0107 idealnym, dlatego praktycznie musisz by\u0107 idealnym we wszystkim. A to jest niemo\u017cliwe i tak si\u0119 nie robi. Zawsze jest mn\u00f3stwo rzeczy do poprawy \u2013 i to jest ca\u0142kowicie normalne.<\/p>\n<p><\/p>\n<h1 id=\"kak-delat-bolshoy-refaktoring\">How to perform large refactorings<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Jak pracujesz nad wydajno\u015bci\u0105? To przecie\u017c problem wszechobecny. Na przyk\u0142ad, czy kiedykolwiek musia\u0142e\u015b pracowa\u0107 nad problemami, kt\u00f3re pojawiaj\u0105 si\u0119 w wyniku przeci\u0119cia si\u0119 du\u017cej ilo\u015bci istniej\u0105cej ju\u017c funkcjonalno\u015bci?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Staram si\u0119 tego unika\u0107. Je\u015bli wiem, \u017ce wydajno\u015b\u0107 b\u0119dzie problemem, zastanawiam si\u0119 nad tym, zanim zaczn\u0119 kodowa\u0107, szczeg\u00f3lnie nad strukturami danych. Ale cz\u0119sto odkrywasz to znacznie p\u00f3\u017aniej. Wtedy musisz podejmowa\u0107 ostateczne \u015brodki i robi\u0107 to, co nazywam \u201eprzepisywaniem i rz\u0105dzeniem\u201d: musisz uchwyci\u0107 wystarczaj\u0105co du\u017c\u0105 cz\u0119\u015b\u0107. Cz\u0119\u015b\u0107 kodu i tak b\u0119dzie musia\u0142a zosta\u0107 przepisana z powodu problem\u00f3w z wydajno\u015bci\u0105 lub z innych powod\u00f3w. Niezale\u017cnie od tego, jaka przyczyna przepisania kodu si\u0119 pojawi, prawie zawsze lepiej przerobi\u0107 wi\u0119ksz\u0105 cz\u0119\u015b\u0107 ni\u017c mniejsz\u0105. W tym momencie wszyscy zaczynaj\u0105 dr\u017ce\u0107 ze strachu: \u201eo rany, nie mo\u017cna dotyka\u0107 tak du\u017cej ilo\u015bci kodu!\u201d. Ale w rzeczywisto\u015bci takie podej\u015bcie zazwyczaj dzia\u0142a znacznie lepiej. Nale\u017cy od razu wzi\u0105\u0107 si\u0119 za du\u017cy problem, otoczy\u0107 go du\u017cym kr\u0119giem i powiedzie\u0107: wszystko, co w tym kr\u0119gu, przepisuj\u0119. Granica jest znacznie mniejsza ni\u017c tre\u015b\u0107 wewn\u0105trz niej, kt\u00f3r\u0105 nale\u017cy wymieni\u0107. A je\u015bli taki zarys granic pozwoli wykona\u0107 prac\u0119 wewn\u0105trz doskonale \u2013 masz woln\u0105 r\u0119k\u0119, r\u00f3b co chcesz. Gdy tylko zrozumiesz problem, proces przepisywania znacznie si\u0119 upraszcza, wi\u0119c bierz du\u017cy kawa\u0142ek!<br \/>\nZ drugiej strony, gdy przepisujesz du\u017c\u0105 cz\u0119\u015b\u0107 i zdajesz sobie spraw\u0119, \u017ce wydajno\u015b\u0107 mo\u017ce sta\u0107 si\u0119 problemem, mo\u017cesz od razu zacz\u0105\u0107 si\u0119 tym martwi\u0107. Zazwyczaj sprowadza si\u0119 to do prostych rzeczy, takich jak \u201enie kopiuj danych, zarz\u0105dzaj danymi tak prosto, jak to mo\u017cliwe, spraw, aby by\u0142y mniejsze\u201d. W du\u017cych przepisywaniach s\u0105 standardowe sposoby na popraw\u0119 wydajno\u015bci. I zazwyczaj kr\u0119c\u0105 si\u0119 wok\u00f3\u0142 danych.<\/p>\n<p><\/p>\n<h1 id=\"model-stoimosti\">Cost model<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: W jednym z podcast\u00f3w wspominali\u015bcie o modelach koszt\u00f3w w kontek\u015bcie wydajno\u015bci. Czy mo\u017cecie wyja\u015bni\u0107, co przez to mieli\u015bcie na my\u015bli?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Oczywi\u015bcie. Urodzi\u0142em si\u0119 w czasach, gdy wydajno\u015b\u0107 procesora by\u0142a niezwykle wa\u017cna. I ta era zn\u00f3w powraca \u2013 los nie jest pozbawiony ironii. Zacz\u0105\u0142em \u017cy\u0107 w czasach maszyn o\u015bmiobitowych, m\u00f3j pierwszy komputer dzia\u0142a\u0142 na 256 bajtach. W\u0142a\u015bnie bajtach. Wszystko by\u0142o bardzo ma\u0142e. Musia\u0142em liczy\u0107 instrukcje i gdy tylko zacz\u0119li\u015bmy przemieszcza\u0107 si\u0119 w g\u00f3r\u0119 stosu j\u0119zyk\u00f3w programowania, j\u0119zyki bra\u0142y na siebie coraz wi\u0119cej. By\u0142 Assember, potem Basic, potem C, a C zajmowa\u0142 si\u0119 wieloma szczeg\u00f3\u0142ami, takimi jak przydzielanie rejestr\u00f3w i dob\u00f3r instrukcji. Ale wszystko by\u0142o dosy\u0107 zrozumia\u0142e i je\u015bli zrobi\u0142em wska\u017anik do instancji zmiennej, to otrzyma\u0142em load, a koszt tej instrukcji jest znany. Sprz\u0119t wydaje znan\u0105 ilo\u015b\u0107 cykli maszynowych, wi\u0119c pr\u0119dko\u015b\u0107 wykonywania r\u00f3\u017cnych rzeczy mo\u017cna obliczy\u0107, sumuj\u0105c wszystkie instrukcje, kt\u00f3re zamierzasz uruchomi\u0107. Ka\u017cde por\u00f3wnanie\/pr\u00f3ba\/ga\u0142\u0105\u017a\/wywo\u0142anie\/\u0142adunek\/przechowywanie mo\u017cna zsumowa\u0107 i powiedzie\u0107: oto czas wykonania. Zajmuj\u0105c si\u0119 popraw\u0105 wydajno\u015bci, na pewno zwr\u00f3cisz uwag\u0119 na to, jakie liczby odpowiadaj\u0105 ma\u0142ym gor\u0105cym cyklom.\u00a0<br \/>\nAle jak tylko prze\u0142\u0105czysz si\u0119 na Jav\u0119, Pythona i podobne rzeczy, szybko oddalasz si\u0119 od niskopoziomowego sprz\u0119tu. Jaki jest koszt wywo\u0142ania gettera w Javie? Je\u015bli JIT w HotSpot wszystko dobrze <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.openjdk.java.net\/display\/HotSpot\/Inlining\">zainline'owa\u0142<\/a><\/noindex>, to b\u0119dzie load, ale je\u015bli tego nie zrobi\u0142 \u2013 to b\u0119dzie wywo\u0142anie funkcji. Poniewa\u017c wywo\u0142anie le\u017cy w gor\u0105cym cyklu, uniewa\u017cni wszystkie inne optymalizacje w tym cyklu. Dlatego rzeczywisty koszt b\u0119dzie znacznie wi\u0119kszy. I tracisz od razu zdolno\u015b\u0107 do spojrzenia na fragment kodu i zrozumienia, co kosztuje jego wykonanie w terminach cykli zegara procesora, u\u017cywanej pami\u0119ci i cache. Wszystko to staje si\u0119 interesuj\u0105ce tylko wtedy, gdy naprawd\u0119 zag\u0142\u0119bisz si\u0119 w wydajno\u015b\u0107.<br \/>\nObecnie znajdujemy si\u0119 w sytuacji, w kt\u00f3rej pr\u0119dko\u015bci procesor\u00f3w od dekady prawie si\u0119 nie zmieniaj\u0105. Stare czasy wracaj\u0105! Ju\u017c nie mo\u017cesz liczy\u0107 na dobr\u0105 wydajno\u015b\u0107 jednow\u0105tkow\u0105. Ale je\u015bli nagle zajmiesz si\u0119 obliczeniami r\u00f3wnoleg\u0142ymi \u2013 to jest szalenie trudne, wszyscy patrz\u0105 na ciebie jak na Jamesa Bonda. Dziesi\u0119ciokrotne przyspieszenia pojawiaj\u0105 si\u0119 zwykle w miejscach, gdzie kto\u015b co\u015b przeoczy\u0142. R\u00f3wnoleg\u0142o\u015b\u0107 wymaga wielu dzia\u0142a\u0144. Aby uzyska\u0107 to \u015bwi\u0119te dziesi\u0119ciokrotne przyspieszenie, musisz zrozumie\u0107 model koszt\u00f3w. Co i ile kosztuje. A do tego potrzebujesz zrozumie\u0107, jak j\u0119zyk wsp\u00f3\u0142pracuje z le\u017c\u0105cym poni\u017cej sprz\u0119tem.<br \/>\nMartin Thompson dobra\u0142 \u015bwietne s\u0142owo na swojego bloga <noindex><a rel=\"nofollow\" href=\"https:\/\/mechanical-sympathy.blogspot.com\/\">Mechanical Sympathy<\/a><\/noindex>! Nale\u017cy rozumie\u0107, co zamierza zrobi\u0107 sprz\u0119t, jak dok\u0142adnie to zrobi i dlaczego w og\u00f3le to robi. Korzystaj\u0105c z tego, do\u015b\u0107 \u0142atwo zacz\u0105\u0107 liczy\u0107 instrukcje i ustali\u0107, gdzie uciekaj\u0105 czas wykonania. Je\u015bli nie masz odpowiedniego przygotowania, po prostu szukasz czarnej kota w ciemnym pokoju. Ci\u0105gle widz\u0119 ludzi, kt\u00f3rzy optymalizuj\u0105 wydajno\u015b\u0107, ale nie maj\u0105 najmniejszego poj\u0119cia, co w og\u00f3le robi\u0105. Maj\u0105 trudno\u015bci i nie posuwaj\u0105 si\u0119 za bardzo naprz\u00f3d. A kiedy bior\u0119 ten sam kawa\u0142ek kodu, dodaj\u0119 kilka drobnych hack\u00f3w i osi\u0105gam pi\u0119ciokrotne lub dziesi\u0119ciokrotne przyspieszenie, oni m\u00f3wi\u0105: no, to niesprawiedliwe, i tak wiedzieli\u015bmy, \u017ce jeste\u015b lepszy. Niesamowite. O czym to ja\u2026 model koszt\u00f3w \u2013 to o tym, za jaki kod piszesz i jak szybko dzia\u0142a on przeci\u0119tnie w ca\u0142ym obrazie.<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: A jak utrzyma\u0107 tak\u0105 ilo\u015b\u0107 w g\u0142owie? Osi\u0105ga si\u0119 to du\u017c\u0105 ilo\u015bci\u0105 do\u015bwiadczenia, prawda? Gdzie mo\u017cna zdoby\u0107 takie do\u015bwiadczenie?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: C\u00f3\u017c, moje do\u015bwiadczenie zdoby\u0142em nie najprostsz\u0105 drog\u0105. Programowa\u0142em w Assemblerze, gdy mo\u017cna by\u0142o zrozumie\u0107 ka\u017cd\u0105 pojedyncz\u0105 instrukcj\u0119. Brzmi g\u0142upio, ale od tamtej pory na zawsze pozosta\u0142 mi w pami\u0119ci zestaw instrukcji Z80. Nie pami\u0119tam imion ludzi ju\u017c po minucie rozmowy, ale pami\u0119tam kod napisany 40 lat temu. Ciekawe, to wygl\u0105da jak syndrom \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\">naukowego idioty<\/a><\/noindex>\u00bb.<\/p>\n<p><\/p>\n<h1 id=\"obuchenie-nizkourovnevym-optimizaciyam\">Learning low-level optimizations<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Czy istnieje jaki\u015b prostszy spos\u00f3b, aby si\u0119 w to wci\u0105gn\u0105\u0107?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Tak i nie. Sprz\u0119t, kt\u00f3rego wszyscy u\u017cywamy, w tym czasie niewiele si\u0119 zmieni\u0142. Wszyscy korzystaj\u0105 z x86, z wyj\u0105tkiem smartfon\u00f3w na Arm. Je\u015bli nie zajmujesz si\u0119 jakim\u015b hardcore\u2019owym embedded, masz to samo. Dobrze, przechod\u017amy dalej. Instrukcje r\u00f3wnie\u017c przez wieki si\u0119 nie zmieni\u0142y. Musisz p\u00f3j\u015b\u0107 i napisa\u0107 co\u015b w assemblerze. Troch\u0119, ale wystarczaj\u0105co, aby zacz\u0105\u0107 rozumie\u0107. Ty si\u0119 u\u015bmiechasz, ale m\u00f3wi\u0119 to zupe\u0142nie powa\u017cnie. Musisz zrozumie\u0107 odpowiednio\u015b\u0107 mi\u0119dzy j\u0119zykiem a sprz\u0119tem. Po tym musisz p\u00f3j\u015b\u0107, napisa\u0107 troch\u0119 i stworzy\u0107 ma\u0142y zabawkowy kompilator dla ma\u0142ego zabawkowego j\u0119zyka. \u201eZabawkowy\u201d oznacza, \u017ce musisz go zrobi\u0107 w rozs\u0105dnym czasie. Mo\u017ce by\u0107 super prosty, ale musi generowa\u0107 instrukcje. Akt generowania instrukcji pozwoli zrozumie\u0107 model koszt\u00f3w dla mostu mi\u0119dzy wysokopoziomowym kodem, w kt\u00f3rym wszyscy pisz\u0105, a kodem maszynowym, kt\u00f3ry jest wykonywany na sprz\u0119cie. Ta odpowiednio\u015b\u0107 wniknie w umys\u0142y w momencie pisania kompilatora. Nawet najbardziej podstawowy kompilator. Po tym mo\u017cna zacz\u0105\u0107 patrze\u0107 na Jav\u0119 i dostrzega\u0107, \u017ce jej semantyczna przepa\u015b\u0107 jest znacznie g\u0142\u0119bsza, a budowanie most\u00f3w nad ni\u0105 jest znacznie trudniejsze. W Javie znacznie trudniej zrozumie\u0107, czy nasz most jest dobry, czy z\u0142y, co sprawi, \u017ce si\u0119 zawali, a co nie. Ale potrzebujesz jakiego\u015b punktu wyj\u015bcia, gdy patrzysz na kod i rozumiesz: \u201eaha, ten getter powinien by\u0107 inlinowany za ka\u017cdym razem\u201d. A potem okazuje si\u0119, \u017ce czasami tak jest, z wyj\u0105tkiem sytuacji, gdy metoda staje si\u0119 za du\u017ca, a JIT zaczyna wci\u0105ga\u0107 wszystko, co popadnie. Wydajno\u015b\u0107 takich miejsc mo\u017cna przewidzie\u0107 natychmiast. Zwykle gettery dzia\u0142aj\u0105 dobrze, ale potem patrzysz na du\u017ce gor\u0105ce p\u0119tle i zauwa\u017casz, \u017ce w nich p\u0142ywaj\u0105 jakie\u015b wywo\u0142ania funkcji, kt\u00f3rych nie wiadomo, co robi\u0105. W tym tkwi problem powszechnego stosowania getter\u00f3w, pow\u00f3d, dla kt\u00f3rego nie s\u0105 inlinowane \u2013 nie wiadomo, czy to getter. Je\u015bli masz superma\u0142\u0105 baz\u0119 kodu, mo\u017cesz j\u0105 po prostu zapami\u0119ta\u0107 i p\u00f3\u017aniej powiedzie\u0107: to jest getter, a to jest setter. W du\u017cej bazie kodu ka\u017cda funkcja \u017cyje swoj\u0105 w\u0142asn\u0105 histori\u0105, kt\u00f3ra w zasadzie nikomu nie jest znana. Profilowanie m\u00f3wi, \u017ce stracili\u015bmy 24% czasu na jakiej\u015b p\u0119tli i aby zrozumie\u0107, co ta p\u0119tla robi, musisz spojrze\u0107 na ka\u017cd\u0105 funkcj\u0119 w \u015brodku. Nie da si\u0119 tego zrozumie\u0107 bez studiowania funkcji, co powa\u017cnie spowalnia proces rozumienia. Dlatego nie u\u017cywam getter\u00f3w i setter\u00f3w, osi\u0105gn\u0105\u0142em nowy poziom!<br \/>\nSk\u0105d wzi\u0105\u0107 model koszt\u00f3w? Oczywi\u015bcie mo\u017cna co\u015b poczyta\u0107... Ale my\u015bl\u0119, \u017ce najlepszym sposobem jest dzia\u0142anie. Zbudowa\u0107 ma\u0142y kompilator, a to b\u0119dzie najlepszy spos\u00f3b, aby zrozumie\u0107 model koszt\u00f3w i zmie\u015bci\u0107 go w sobie. Ma\u0142y kompilator, kt\u00f3ry nadawa\u0142by si\u0119 do programowania mikrofal\u00f3wki \u2013 to zadanie dla nowicjusza. No, mam na my\u015bli, \u017ce je\u015bli ju\u017c masz umiej\u0119tno\u015bci programowania, to powinno wystarczy\u0107. Wszystkie te rzeczy, jak sparsowanie ci\u0105gu, kt\u00f3ry b\u0119dzie jakim\u015b wyra\u017ceniem algebraicznym, wydobycie stamt\u0105d instrukcji operacji matematycznych w odpowiedniej kolejno\u015bci, wzi\u0119cie odpowiednich warto\u015bci z rejestr\u00f3w \u2013 to wszystko robi si\u0119 w mgnieniu oka. I podczas gdy to robisz, zostanie to wydrukowane w m\u00f3zgu. My\u015bl\u0119, \u017ce wszyscy wiedz\u0105, czym zajmuje si\u0119 kompilator. To da zrozumienie modelu koszt\u00f3w.<\/p>\n<p><\/p>\n<h1 id=\"prakticheskie-primery-uluchsheniya-proizvoditelnosti\">Practical examples of performance improvements<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Na co jeszcze warto zwr\u00f3ci\u0107 uwag\u0119 przy pracy nad wydajno\u015bci\u0105?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Struktury danych. Tak, nawiasem m\u00f3wi\u0105c, dawno nie prowadzi\u0142em tych zaj\u0119\u0107... <noindex>Rocket School<\/noindex>. To by\u0142o zabawne, ale wymaga\u0142o takiego wysi\u0142ku, a ja mam przecie\u017c jeszcze swoje \u017cycie! Dobrze. Ot\u00f3\u017c, na jednym z du\u017cych i interesuj\u0105cych zaj\u0119\u0107, 'Dok\u0105d ucieka Twoja wydajno\u015b\u0107', dawa\u0142em studentom przyk\u0142ad: dwa i p\u00f3\u0142 gigabajta danych fintech wczytywano z pliku CSV, a nast\u0119pnie trzeba by\u0142o obliczy\u0107 liczb\u0119 sprzedawanych produkt\u00f3w. Zwyk\u0142e dane rynkowe. Pakiety UDP, przekszta\u0142cone na format tekstowy, si\u0119gaj\u0105ce lat 70-tych. Chicago Mercantile Exchange \u2013 r\u00f3\u017cne rzeczy, takie jak olej, kukurydza, soja i tym podobne. Nale\u017ca\u0142o policzy\u0107 te produkty, liczb\u0119 transakcji, \u015bredni\u0105 warto\u015b\u0107 obrot\u00f3w i towar\u00f3w, itd. To do\u015b\u0107 prosta matematyka handlowa: znale\u017a\u0107 kod produktu (to 1-2 znaki w tabeli haszy), uzyska\u0107 sum\u0119, doda\u0107 j\u0105 do jednego z zestaw\u00f3w transakcji, doda\u0107 wolumen, doda\u0107 koszt, i kilka innych rzeczy. Bardzo prosta matematyka. Prosta implementacja by\u0142a bardzo bezpo\u015brednia: wszystko znajduje si\u0119 w pliku, czytam plik i przechodz\u0119 przez niego, dziel\u0105c poszczeg\u00f3lne rekordy na wiersze w Javie, szukam w nich potrzebnych rzeczy i sumuj\u0119 wed\u0142ug powy\u017cszej matematyki. I to dzia\u0142a z jak\u0105\u015b niewielk\u0105 pr\u0119dko\u015bci\u0105. <\/p>\n<p><\/p>\n<p>Z takim podej\u015bciem wszystko staje si\u0119 jasne, co si\u0119 dzieje, a r\u00f3wnoleg\u0142e obliczenia tutaj nie pomog\u0105, prawda? Okazuje si\u0119, \u017ce pi\u0119ciokrotny wzrost wydajno\u015bci mo\u017cna osi\u0105gn\u0105\u0107 po prostu wybieraj\u0105c odpowiednie struktury danych. To zaskakuje nawet do\u015bwiadczonych programist\u00f3w! W moim konkretnym przypadku chodzi\u0142o o to, \u017ce nie nale\u017cy dokonywa\u0107 alokacji pami\u0119ci w gor\u0105cej p\u0119tli. C\u00f3\u017c, to nie ca\u0142a prawda, ale og\u00f3lnie \u2013 nie nale\u017cy alokowa\u0107 \u201eraz na X\u201d, kiedy X jest wystarczaj\u0105co du\u017ce. Kiedy X wynosi dwa i p\u00f3\u0142 gigabajta, nie nale\u017cy alokowa\u0107 niczego \u201eraz za liter\u0119\u201d, ani \u201eraz za lini\u0119\u201d, ani \u201eraz za pole\u201d, nic w tym stylu. To w\u0142a\u015bnie na to marnuje si\u0119 czas. Jak to w og\u00f3le dzia\u0142a? Wyobra\u017a sobie, \u017ce wywo\u0142uj\u0119 <code>String.split()<\/code> lub <code>BufferedReader.readLine()<\/code>. <code>Readline<\/code> tworzy ci\u0105g z zestawu bajt\u00f3w, kt\u00f3re przysz\u0142y przez sie\u0107, raz dla ka\u017cdej linii, dla ka\u017cdej z setek milion\u00f3w linii. Bior\u0119 t\u0119 lini\u0119, analizuj\u0119 j\u0105 i odrzucam. Dlaczego odrzucam \u2013 c\u00f3\u017c, ju\u017c j\u0105 przetworzy\u0142em, to wszystko. Tak wi\u0119c dla ka\u017cdego bajtu, kt\u00f3ry odczytuj\u0119 z tych 2.7G, zapisane zostan\u0105 dwa znaki w ci\u0105gu, co daje ju\u017c 5.4G, a potem nie s\u0105 mi do niczego potrzebne, wi\u0119c s\u0105 odrzucane. Je\u015bli spojrze\u0107 na przepustowo\u015b\u0107 pami\u0119ci, \u0142adujemy 2.7G, kt\u00f3re przechodzi przez pami\u0119\u0107 i magistral\u0119 pami\u0119ci w procesorze, a nast\u0119pnie dwa razy wi\u0119cej wysy\u0142a si\u0119 do ci\u0105gu w pami\u0119ci, a wszystko to jest przetwarzane podczas tworzenia ka\u017cdej nowej linii. Ale musz\u0119 j\u0105 przeczyta\u0107, sprz\u0119t j\u0105 odczytuje, nawet je\u015bli potem wszystko b\u0119dzie przetarte. A musz\u0119 j\u0105 zapisa\u0107, bo stworzy\u0142em ci\u0105g i pami\u0119ci podr\u0119czne si\u0119 przepe\u0142ni\u0142y \u2013 pami\u0119\u0107 podr\u0119czna nie mo\u017ce pomie\u015bci\u0107 2.7G. W sumie, dla ka\u017cdego odczytanego bajtu czytam jeszcze dwa dodatkowe bajty i zapisuj\u0119 dwa dodatkowe bajty, i w efekcie mamy proporcj\u0119 4:1 \u2013 w takim stosunku marnujemy przepustowo\u015b\u0107 pami\u0119ci. A potem okazuje si\u0119, \u017ce je\u015bli robi\u0119 <code>String.split()<\/code> \u2013 to robi\u0119 to z pewno\u015bci\u0105 nie po raz ostatni, tam w \u015brodku mo\u017ce by\u0107 jeszcze 6-7 p\u00f3l. Dlatego klasyczny kod do odczytu CSV z p\u00f3\u017aniejszym parsowaniem linii prowadzi do strat przepustowo\u015bci pami\u0119ci w okolicach 14:1 w por\u00f3wnaniu do tego, co naprawd\u0119 chcia\u0142by\u015b mie\u0107. Je\u015bli wyrzuci\u0107 te alokacje, mo\u017cna uzyska\u0107 pi\u0119ciokrotne przyspieszenie. <\/p>\n<p><\/p>\n<p>I to nie jest wcale takie trudne. Je\u015bli spojrzysz na kod z odpowiedniej perspektywy, wszystko staje si\u0119 do\u015b\u0107 proste, gdy zrozumiesz istot\u0119 problemu. Nie powinno si\u0119 w og\u00f3le przestawa\u0107 przydziela\u0107 pami\u0119ci: problem polega tylko na tym, \u017ce co\u015b przydzielasz, a to natychmiast umiera, spalaj\u0105c po drodze wa\u017cny zas\u00f3b, kt\u00f3rym w tym przypadku jest przepustowo\u015b\u0107 pami\u0119ci. A wszystko to przek\u0142ada si\u0119 na spadek wydajno\u015bci. Na x86 zazwyczaj trzeba aktywnie spala\u0107 cykle procesora, a tutaj spali\u0142e\u015b ca\u0142\u0105 pami\u0119\u0107 znacznie wcze\u015bniej. Rozwi\u0105zaniem jest zmniejszenie liczby przydzielania.\u00a0<br \/>\nInna cz\u0119\u015b\u0107 problemu polega na tym, \u017ce je\u015bli uruchomisz profiler, gdy sko\u0144czy si\u0119 pasmo pami\u0119ci, w momencie, gdy to si\u0119 zdarza, zazwyczaj czekasz na powr\u00f3t cache, poniewa\u017c jest on pe\u0142en ba\u0142aganu, kt\u00f3ry w\u0142a\u015bnie stworzy\u0142e\u015b \u2013 wszystkich tych wierszy. Dlatego ka\u017cda operacja za\u0142adunku czy zapisu staje si\u0119 wolna, poniewa\u017c prowadzi do nietrafionych odwo\u0142a\u0144 do cache \u2013 ca\u0142y cache sta\u0142 si\u0119 wolny, czekaj\u0105c na usuni\u0119cie \u015bmieci. Dlatego profiler pokazuje jedynie ciep\u0142y, losowy szum, rozmazany wzd\u0142u\u017c ca\u0142ego cyklu \u2013 nie b\u0119dzie \u017cadnej osobnej gor\u0105cej instrukcji ani miejsca w kodzie. Tylko szum. A je\u015bli spojrzysz na cykle GC, wszystkie b\u0119d\u0105 w Young Generation i niezwykle szybkie \u2013 mikrosekundy lub maksymalnie milisekundy. Bowiem ca\u0142a ta pami\u0119\u0107 umiera natychmiast. Przydzielasz miliardy gigabajt\u00f3w, a on je przycina, i przycina, i znowu przycina. Wszystko to dzieje si\u0119 bardzo szybko. Tak wi\u0119c mamy tanie cykle GC, ciep\u0142y szum wzd\u0142u\u017c ca\u0142ego cyklu, ale chcemy uzyska\u0107 pi\u0119ciokrotne przyspieszenie. W tym momencie powinno w g\u0142owie zapali\u0107 si\u0119 co\u015b i zabrzmie\u0107: \"dlaczego tak?!\". Przepe\u0142nienie pasma pami\u0119ci nie objawia si\u0119 w klasycznym debuggerze, trzeba uruchomi\u0107 debugger sprz\u0119towych licznik\u00f3w wydajno\u015bci i zobaczy\u0107 to samodzielnie i bezpo\u015brednio. A nie bezpo\u015brednio mo\u017cna podejrzewa\u0107 na podstawie tych trzech objaw\u00f3w. Trzeci objaw \u2013 to gdy patrzysz, co przydzielasz, pytasz profilera, a on odpowiada: \"Zrobi\u0142e\u015b miliard wierszy, ale GC dzia\u0142a\u0142 za darmo\". Kiedy to si\u0119 zdarza, rozumiesz, \u017ce stworzy\u0142e\u015b zbyt wiele obiekt\u00f3w i spali\u0142e\u015b ca\u0142e pasmo pami\u0119ci. Jest spos\u00f3b, aby si\u0119 z tym upora\u0107, ale nie jest oczywisty.\u00a0<\/p>\n<p><\/p>\n<p>Problem z struktur\u0105 danych: go\u0142a struktura, kt\u00f3ra le\u017cy u podstaw wszystkiego, co si\u0119 dzieje, jest zbyt du\u017ca, zajmuje 2,7G na dysku, dlatego bardzo niepo\u017c\u0105dane jest jej kopiowanie \u2013 chcia\u0142oby si\u0119 za\u0142adowa\u0107 j\u0105 od razu z sieciowego bufora bajt\u00f3w do rejestr\u00f3w, aby nie czyta\u0107 i nie zapisywa\u0107 do niej pi\u0119\u0107 razy. Niestety, Java domy\u015blnie nie oferuje takiej biblioteki w sk\u0142adzie JDK. Ale to jest trywialne, prawda? W gruncie rzeczy to 5-10 linii kodu na wdro\u017cenie w\u0142asnego buforowanego loadera linii, kt\u00f3ry na\u015bladuje dzia\u0142anie klasy string, b\u0119d\u0105c jednocze\u015bnie obwolut\u0105 wok\u00f3\u0142 dolnego bufora bajt\u00f3w. W rezultacie okazuje si\u0119, \u017ce pracujesz niemal jak ze stringami, ale tak naprawd\u0119 przesuwaj\u0105 si\u0119 wska\u017aniki na bufor, a surowe bajty nie s\u0105 nigdzie kopiowane, i w ten spos\u00f3b wielokrotnie wykorzystujesz te same bufory, a system operacyjny ch\u0119tnie przejmuje rzeczy, do kt\u00f3rych jest przeznaczony, jak ukryta podw\u00f3jna buforowanie tych bufor\u00f3w bajtowych, a ty ju\u017c wi\u0119cej nie przetwarzasz bez ko\u0144ca zb\u0119dnych danych. Przy okazji, rozumiecie, \u017ce podczas pracy z GC gwarantuje si\u0119, \u017ce ka\u017cda alokacja pami\u0119ci nie b\u0119dzie widoczna dla procesora po ostatniej p\u0119tli GC? Dlatego to wszystko nie mo\u017ce by\u0107 w cache'u, a potem zdarza si\u0119 100% gwarantowane spud\u0142owanie. Podczas pracy z wska\u017anikiem, na architekturze x86 odczyt rejestru z pami\u0119ci zajmuje 1-2 takty, i kiedy to si\u0119 ju\u017c wydarzy, p\u0142acisz, p\u0142acisz, p\u0142acisz, poniewa\u017c ca\u0142a pami\u0119\u0107 <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Cache_inclusion_policy\">NINE cache'ach<\/a><\/noindex> \u2013 i to jest koszt alokacji pami\u0119ci. Prawdziwy koszt.<\/p>\n<p><\/p>\n<p>Innymi s\u0142owy, struktury danych to co\u015b, co najtrudniej zmieni\u0107. A kiedy ju\u017c u\u015bwiadomisz sobie, \u017ce wybra\u0142e\u015b niew\u0142a\u015bciw\u0105 struktur\u0119 danych, kt\u00f3ra p\u00f3\u017aniej zrujnuje wydajno\u015b\u0107, zazwyczaj wymaga to znacz\u0105cej pracy, a je\u015bli tego nie zrobisz, b\u0119dzie tylko gorzej. Przede wszystkim trzeba my\u015ble\u0107 o strukturach danych, to jest wa\u017cne. Podstawowy koszt spoczywa na z\u0142o\u017conych strukturach danych, kt\u00f3re zaczynamy u\u017cywa\u0107 w stylu \u201eskopiowa\u0142em struktur\u0119 danych X do struktury danych Y, bo forma Y bardziej mi odpowiada\u201d. Ale operacja kopiowania (kt\u00f3ra wydaje si\u0119 tania) w rzeczywisto\u015bci zu\u017cywa pasmo pami\u0119ci, i tu jest zakopane ca\u0142e stracone czas wykonania. Je\u015bli mam gigantyczny ci\u0105g z JSON i chc\u0119 przekszta\u0142ci\u0107 go w zorganizowane drzewo DOM z POJO lub co\u015b w tym stylu, operacja parsowania tego ci\u0105gu i budowania POJO, a potem nowe odwo\u0142anie do POJO w przysz\u0142o\u015bci zamieni\u0105 si\u0119 w dodatkowy koszt \u2013 to nie jest tanie. Z wyj\u0105tkiem przypadku, gdy b\u0119dziesz korzysta\u0107 z POJO znacznie cz\u0119\u015bciej ni\u017c z ci\u0105gu. Na szybko, zamiast tego mo\u017cna spr\u00f3bowa\u0107 rozkodowa\u0107 ci\u0105g i wyci\u0105gn\u0105\u0107 tylko to, co potrzebne, nie przekszta\u0142caj\u0105c w \u017cadne POJO. Je\u015bli wszystko to dzieje si\u0119 na drodze, na kt\u00f3rej wymagana jest maksymalna wydajno\u015b\u0107, nie ma mowy o POJO \u2013 trzeba jako\u015b grzeba\u0107 bezpo\u015brednio w ci\u0105gu.<\/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>: Powiedzia\u0142e\u015b, \u017ce aby zrozumie\u0107 model koszt\u00f3w, trzeba stworzy\u0107 sw\u00f3j ma\u0142y j\u0119zyk\u2026<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Nie j\u0119zyk, a kompilator. J\u0119zyk i kompilator to r\u00f3\u017cne rzeczy. Najwa\u017cniejsza r\u00f3\u017cnica - w swojej g\u0142owie.\u00a0<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Przy okazji, z tego co wiem, eksperymentujesz z tworzeniem w\u0142asnych j\u0119zyk\u00f3w. Po co?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Bo dlatego, \u017ce mog\u0119! Jestem w po\u0142owie na emeryturze, wi\u0119c to moje hobby. Przez ca\u0142e \u017cycie realizowa\u0142em j\u0119zyki innych ludzi. Du\u017co pracowa\u0142em nad stylem pisania kodu. A tak\u017ce dlatego, \u017ce dostrzegam problemy w innych j\u0119zykach. Widzia\u0142em, \u017ce s\u0105 lepsze sposoby na wykonywanie codziennych zada\u0144. I zamierzam z nich skorzysta\u0107. Po prostu mam do\u015b\u0107 widzenia problem\u00f3w w sobie, w Javie, w Pythonie i w ka\u017cdym innym j\u0119zyku. Obecnie pisz\u0119 w React Native, JavaScript i Elm jako hobby, kt\u00f3re nie dotyczy emerytury, a aktywnej pracy. R\u00f3wnie\u017c pisz\u0119 w Pythonie i prawdopodobnie b\u0119d\u0119 kontynuowa\u0142 prace nad uczeniem maszynowym dla backend\u00f3w Javy. Istnieje wiele popularnych j\u0119zyk\u00f3w i ka\u017cdy z nich ma interesuj\u0105ce cechy. Ka\u017cdy jest dobry w czym\u015b swoim i mo\u017cna spr\u00f3bowa\u0107 po\u0142\u0105czy\u0107 wszystkie te funkcje w jedn\u0105 ca\u0142o\u015b\u0107. Tak wi\u0119c zajmuj\u0119 si\u0119 badaniem interesuj\u0105cych dla mnie rzeczy, zachowaniem j\u0119zyka, pr\u00f3buj\u0119 wymy\u015bli\u0107 sensown\u0105 semantyk\u0119. I jak na razie mi si\u0119 udaje! Aktualnie zmagam si\u0119 z semantyk\u0105 pami\u0119ci, poniewa\u017c chcia\u0142bym mie\u0107 j\u0105 tak jak w C i Javie, uzyska\u0107 silny model pami\u0119ci oraz semantyk\u0119 pami\u0119ci dla za\u0142adunk\u00f3w i zapis\u00f3w. Jednocze\u015bnie mam mie\u0107 automatyczne wnioskowanie typ\u00f3w jak w Haskellu. Oto, pr\u00f3buj\u0119 po\u0142\u0105czy\u0107 Haskell-podobne wnioskowanie typ\u00f3w z pami\u0119ci\u0105 dzia\u0142aj\u0105c\u0105 jak w C i Javie. Tym zajmuj\u0119 si\u0119 przez ostatnie 2-3 miesi\u0105ce, na przyk\u0142ad.<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Je\u015bli tworzysz j\u0119zyk, kt\u00f3ry czerpie najlepsze aspekty z innych j\u0119zyk\u00f3w, czy my\u015bla\u0142e\u015b, \u017ce kto\u015b zrobi odwrotnie: we\u017amie twoje pomys\u0142y i u\u017cyje ich u siebie?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: W\u0142a\u015bnie w ten spos\u00f3b powstaj\u0105 nowe j\u0119zyki! Dlaczego Java jest podobna do C? Poniewa\u017c C mia\u0142 dobry sk\u0142adnik, kt\u00f3ry wszyscy rozumieli i Java inspirowa\u0142a si\u0119 tym sk\u0142adnikiem, dodaj\u0105c do niego bezpiecze\u0144stwo typ\u00f3w, sprawdzanie granic tablic, GC, a tak\u017ce poprawili niekt\u00f3re rzeczy z C. Dodali swoje. Ale inspirowali si\u0119 do\u015b\u0107 mocno, prawda? Wszyscy stoj\u0105 na ramionach gigant\u00f3w, kt\u00f3rzy byli przed nimi \u2013 w ten spos\u00f3b dokonuje si\u0119 post\u0119p.<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Jak rozumiem, tw\u00f3j j\u0119zyk b\u0119dzie bezpieczny w kwestii u\u017cycia pami\u0119ci. Czy my\u015bla\u0142e\u015b o wdro\u017ceniu czego\u015b w rodzaju borrow checkera z Rust? Patrzy\u0142e\u015b na to, co o tym s\u0105dzisz?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: C od lat towarzyszy mi w programowaniu, wsz\u0119dzie wykorzystuj\u0105c malloc i free, a tak\u017ce zarz\u0105dzaj\u0105c czasem \u017cycia r\u0119cznie. Wiecie, 90-95% r\u0119cznie zarz\u0105dzanego czasu \u017cycia ma t\u0119 sam\u0105 struktur\u0119. I to bardzo, bardzo boli zajmowa\u0107 si\u0119 tym r\u0119cznie. Chcia\u0142bym, aby kompilator po prostu m\u00f3wi\u0142, co si\u0119 dzieje i co osi\u0105gn\u0105\u0142em swoimi dzia\u0142aniami. W niekt\u00f3rych przypadkach borrow checker robi to automatycznie. Musi r\u00f3wnie\u017c automatycznie wydobywa\u0107 informacje, wszystko rozumie\u0107, a nawet nie obarcza\u0107 mnie konieczno\u015bci\u0105 wy\u0142o\u017cenia tego zrozumienia. Powinien przynajmniej przeprowadzi\u0107 lokaln\u0105 analiz\u0119 ucieczki, a tylko je\u015bli mu si\u0119 to nie uda, wtedy konieczne jest dodawanie adnotacji typ\u00f3w, kt\u00f3re opisywa\u0142yby czas \u017cycia \u2013 a taki schemat jest znacznie bardziej skomplikowany ni\u017c borrow checker czy jakikolwiek istniej\u0105cy kontroler pami\u0119ci. Wyb\u00f3r mi\u0119dzy \u201ewszystko w porz\u0105dku\u201d a \u201enic nie zrozumia\u0142em\u201d \u2013 nie, powinno by\u0107 co\u015b lepszego.\u00a0<br \/>\nJako osoba, kt\u00f3ra napisa\u0142a wiele kodu w C, uwa\u017cam, \u017ce wsparcie automatycznego zarz\u0105dzania czasem \u017cycia to kluczowa kwestia. Dodatkowo denerwuje mnie, jak bardzo Java wykorzystuje pami\u0119\u0107, a g\u0142\u00f3wnym problemem jest GC. W przypadku alokacji pami\u0119ci w Javie nie otrzymasz pami\u0119ci, kt\u00f3ra by\u0142a lokalna w ostatniej iteracji GC. W j\u0119zykach z dok\u0142adniejszym zarz\u0105dzaniem pami\u0119ci\u0105 nie ma takiego problemu. Gdy wywo\u0142ujesz malloc, od razu otrzymujesz pami\u0119\u0107, kt\u00f3ra zazwyczaj by\u0142a w\u0142a\u015bnie u\u017cywana. Zwykle robisz jakie\u015b tymczasowe operacje z pami\u0119ci\u0105 i natychmiast j\u0105 zwracasz. I wraca ona natychmiast do puli malloc-a, a nast\u0119pny cykl malloc-a ponownie j\u0105 wydobywa. Dlatego rzeczywiste wykorzystanie pami\u0119ci ogranicza si\u0119 do zestawu \u017cywych obiekt\u00f3w w danym momencie, plus wycieki. Je\u015bli nie masz powa\u017cnych wyciek\u00f3w, wi\u0119kszo\u015b\u0107 pami\u0119ci osiada w cache i procesorze, co dzia\u0142a szybko. Jednak wymaga to du\u017co r\u0119cznego zarz\u0105dzania pami\u0119ci\u0105 z u\u017cyciem malloc i free, wywo\u0142ywanych we w\u0142a\u015bciwej kolejno\u015bci i we w\u0142a\u015bciwym miejscu. Rust mo\u017ce poradzi\u0107 sobie z tym samodzielnie i w wielu przypadkach daje nawet lepsz\u0105 wydajno\u015b\u0107, poniewa\u017c zu\u017cycie pami\u0119ci ogranicza si\u0119 do bie\u017c\u0105cych oblicze\u0144 \u2013 w przeciwie\u0144stwie do oczekiwania na nast\u0119pny cykl GC, kt\u00f3ry zwolni pami\u0119\u0107. W rezultacie zyskali\u015bmy bardzo interesuj\u0105cy spos\u00f3b na popraw\u0119 wydajno\u015bci. I ca\u0142kiem pot\u0119\u017cny \u2013 m\u00f3wi\u0119 to z do\u015bwiadczenia, pracuj\u0105c nad przetwarzaniem danych w fintechu, co pozwala\u0142o na pi\u0119ciokrotne przyspieszenie. To do\u015b\u0107 du\u017ce przyspieszenie, zw\u0142aszcza w \u015bwiecie, w kt\u00f3rym procesory nie staj\u0105 si\u0119 szybsze, a my wci\u0105\u017c czekamy na ulepszenia.<\/p>\n<p><\/p>\n<h1 id=\"karera-performans-inzhenera\">Career of a performance engineer<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>Chcia\u0142bym te\u017c zapyta\u0107 o ca\u0142\u0105 karier\u0119. Sta\u0142e\u015b si\u0119 znany dzi\u0119ki pracy przy JIT w HotSpot, a potem przeszed\u0142e\u015b do Azul \u2013 r\u00f3wnie\u017c firm\u0105 zajmuj\u0105c\u0105 si\u0119 JVM. Jednak bardziej koncentrowa\u0142e\u015b si\u0119 na sprz\u0119cie ni\u017c oprogramowaniu. A potem nagle przeszed\u0142e\u015b na Big Data i uczenie maszynowe, a potem na wykrywanie oszustw. Jak to si\u0119 sta\u0142o? To bardzo r\u00f3\u017cne obszary rozwoju.<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Ju\u017c od d\u0142u\u017cszego czasu zajmuj\u0119 si\u0119 programowaniem i uda\u0142o mi si\u0119 zaznaczy\u0107 swoj\u0105 obecno\u015b\u0107 w r\u00f3\u017cnych projektach. Gdy ludzie m\u00f3wi\u0105: \u201eo, to ty ten, kt\u00f3ry stworzy\u0142 JIT dla Javy!\u201d, zawsze mnie to bawi. A wcze\u015bniej zajmowa\u0142em si\u0119 klonem PostScript \u2013 tego j\u0119zyka, kt\u00f3rego Apple kiedy\u015b u\u017cywa\u0142o do swoich drukarek laserowych. A przed tym pracowa\u0142em nad implementacj\u0105 j\u0119zyka Forth. My\u015bl\u0119, \u017ce wsp\u00f3lnym motywem w moim \u017cyciu jest tworzenie narz\u0119dzi. Przez ca\u0142e \u017cycie tworz\u0119 narz\u0119dzia, dzi\u0119ki kt\u00f3rym inni pisz\u0105 swoje niesamowite programy. Zajmowa\u0142em si\u0119 r\u00f3wnie\u017c rozwijaniem system\u00f3w operacyjnych, sterownik\u00f3w, debugger\u00f3w na poziomie j\u0105dra oraz j\u0119zyk\u00f3w do tworzenia system\u00f3w operacyjnych, kt\u00f3re zaczyna\u0142y si\u0119 od prostych pomys\u0142\u00f3w, ale z czasem stawa\u0142y si\u0119 coraz bardziej skomplikowane. G\u0142\u00f3wna tematyka jednak to \u2013 tworzenie narz\u0119dzi. Du\u017ca cz\u0119\u015b\u0107 mojego \u017cycia min\u0119\u0142a mi\u0119dzy Azul a Sun i dotyczy\u0142a Javy. Gdy jednak zaj\u0105\u0142em si\u0119 Big Data i uczeniem maszynowym, zn\u00f3w za\u0142o\u017cy\u0142em swoj\u0105 eleganck\u0105 czapk\u0119 i powiedzia\u0142em: \u201eO, teraz mamy nietrywialny problem, a tutaj dzieje si\u0119 mn\u00f3stwo interesuj\u0105cych rzeczy i ludzi robi\u0105cych co\u015b\u201d. To doskona\u0142a droga do rozwoju, kt\u00f3r\u0119dy warto pod\u0105\u017ca\u0107. <\/p>\n<p><\/p>\n<p>Tak, bardzo lubi\u0119 obliczenia rozproszone. Moja pierwsza praca mia\u0142a miejsce w studenckich czasach, gdzie programowa\u0142em w C nad projektem reklamowym. To by\u0142y obliczenia rozproszone na chipach Zilog Z80, kt\u00f3re zbiera\u0142y dane do analogowego rozpoznawania tekst\u00f3w, przeprowadzanego przez rzeczywisty analogowy analizator. To by\u0142 fascynuj\u0105cy i zupe\u0142nie niezwyk\u0142y temat. Jednak pojawia\u0142y si\u0119 problemy, cz\u0119\u015b\u0107 danych nie by\u0142a rozpoznawana poprawnie, wi\u0119c trzeba by\u0142o wyci\u0105ga\u0107 obrazek i pokazywa\u0107 go osobie, kt\u00f3ra mog\u0142a to przeczyta\u0107, a ta informowa\u0142a, co tam by\u0142o napisane. W zwi\u0105zku z tym istnia\u0142y zadania zwi\u0105zane z danymi, a te zadania mia\u0142y sw\u00f3j w\u0142asny j\u0119zyk. By\u0142 backend, kt\u00f3ry to wszystko przetwarza\u0142 \u2013 r\u00f3wnolegle dzia\u0142aj\u0105ce Z80 z uruchomionymi terminalami vt100 \u2013 po jednym na osob\u0119. Istnia\u0142 model programowania r\u00f3wnoleg\u0142ego na Z80. Pewien wsp\u00f3lny fragment pami\u0119ci, kt\u00f3ry dzieli\u0142y wszystkie Z80 w konfiguracji typu \u201egwiazda\u201d; dzieli\u0142 si\u0119 tak\u017ce szyn\u0105 baga\u017cow\u0105, a po\u0142owa RAM dzieli\u0142a si\u0119 w sieci, podczas gdy druga po\u0142owa by\u0142a prywatna lub wykorzystywana na co\u015b innego. Z\u0142o\u017cony i sensowny system rozproszony z dzielon\u0105\u2026 p\u00f3\u0142dzielon\u0105 pami\u0119ci\u0105. Kiedy to mia\u0142o miejsce\u2026 Ju\u017c nawet nie pami\u0119tam, gdzie\u015b w po\u0142owie lat 80. To by\u0142o naprawd\u0119 dawno temu.\u00a0<br \/>\nTak, mo\u017cna powiedzie\u0107, \u017ce 30 lat to do\u015b\u0107 dawno. Problemy zwi\u0105zane z obliczeniami rozproszonymi istniej\u0105 ju\u017c od d\u0142u\u017cszego czasu, ludzie od zawsze zmagali si\u0119 z <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>-klasterami. Takie klastry wygl\u0105daj\u0105 jak\u2026 Na przyk\u0142ad: jest Ethernet, a tw\u00f3j szybki x86 jest do niego pod\u0142\u0105czony, i teraz chcesz uzyska\u0107 fake shared memory, poniewa\u017c nikt wtedy nie m\u00f3g\u0142 zajmowa\u0107 si\u0119 kodowaniem rozproszonych oblicze\u0144, to by\u0142o zbyt trudne, wi\u0119c powsta\u0142a fake shared memory z ochron\u0105 stron pami\u0119ci na x86. Je\u015bli pisa\u0142e\u015b w t\u0119 stron\u0119, informowali\u015bmy pozosta\u0142e procesory, \u017ce je\u017celi uzyskaj\u0105 dost\u0119p do tej samej shared memory, trzeba j\u0105 za\u0142adowa\u0107 z twojego wpisu. W ten spos\u00f3b powsta\u0142 co\u015b w rodzaju protoko\u0142u wspieraj\u0105cego koherencj\u0119 pami\u0119ci podr\u0119cznej oraz oprogramowanie do tego. Ciekawa koncepcja. Prawdziwym problemem, oczywi\u015bcie, by\u0142a inna kwestia. Wszystko to dzia\u0142a\u0142o, ale szybko napotyka\u0142e\u015b problemy z wydajno\u015bci\u0105, poniewa\u017c nikt nie rozumia\u0142 modelu wydajno\u015bci na wystarczaj\u0105co dobrym poziomie \u2013 jakie s\u0105 wzorce dost\u0119pu do pami\u0119ci, jak sprawi\u0107, \u017ceby w\u0119z\u0142y nie pingowa\u0142y si\u0119 nawzajem w niesko\u0144czono\u015b\u0107, i tak dalej. <\/p>\n<p><\/p>\n<p>W H2O wymy\u015bli\u0142em co\u015b takiego: to sami tw\u00f3rcy odpowiadaj\u0105 za okre\u015blenie, gdzie znajduje si\u0119 r\u00f3wnoleg\u0142o\u015b\u0107, a gdzie jej nie ma. Stworzy\u0142em model kodowania, kt\u00f3ry sprawia, \u017ce pisanie kodu o wysokiej wydajno\u015bci sta\u0142o si\u0119 \u0142atwe i proste. Natomiast napisanie wolno dzia\u0142aj\u0105cego kodu jest trudne, b\u0119dzie wygl\u0105da\u0107 \u017ale. Trzeba si\u0119 naprawd\u0119 postara\u0107, \u017ceby napisa\u0107 wolny kod, b\u0119dziesz musia\u0142 u\u017cy\u0107 niestandardowych metod. Zwalniaj\u0105cy kod wida\u0107 na pierwszy rzut oka. W konsekwencji zazwyczaj pisze si\u0119 kod, kt\u00f3ry dzia\u0142a szybko, ale musisz poradzi\u0107 sobie z tym, co zrobi\u0107 w przypadku wsp\u00f3\u0142dzielonej pami\u0119ci. To wszystko wi\u0105\u017ce si\u0119 z du\u017cymi tablicami, a zachowanie tam przypomina nie-woltalne du\u017ce tablice w r\u00f3wnoleg\u0142ej Javie. Wyobra\u017a sobie, \u017ce dwa w\u0105tki pisz\u0105 do r\u00f3wnoleg\u0142ej tablicy, jeden z nich wygrywa, a drugi, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, przegrywa, i nie wiesz, kto jest kim. Je\u015bli nie s\u0105 one woltalne, to kolejno\u015b\u0107 mo\u017ce by\u0107 dowolna \u2013 i to naprawd\u0119 dzia\u0142a. Ludzie rzeczywi\u015bcie dbaj\u0105 o kolejno\u015b\u0107 operacji, prawid\u0142owo umieszczaj\u0105 volatile i w odpowiednich miejscach oczekuj\u0105 problem\u00f3w z wydajno\u015bci\u0105 zwi\u0105zanych z pami\u0119ci\u0105. W przeciwnym razie po prostu pisaliby kod jako p\u0119tle od 1 do N, gdzie N to jakies tryliony, maj\u0105c nadziej\u0119, \u017ce wszystkie skomplikowane przypadki automatycznie stan\u0105 si\u0119 r\u00f3wnoleg\u0142e \u2013 i tam to nie dzia\u0142a. Ale w H2O to nie jest ani Java, ani Scala, mo\u017cna to nazwa\u0107 \u201eJava minus minus\u201d, je\u015bli chcesz. To bardzo zrozumia\u0142y styl programowania, przypominaj\u0105cy pisanie prostego kodu w C lub Javie z p\u0119tlami i tablicami. Ale mo\u017cna przetwarza\u0107 pami\u0119\u0107 w terabajtach. Nadal korzystam z H2O. Od czasu do czasu u\u017cywam w r\u00f3\u017cnych projektach \u2013 i to wci\u0105\u017c jest najszybsza rzecz, wyprzedzaj\u0105ca konkurencj\u0119 dziesi\u0105tki razy. Je\u015bli zajmujesz si\u0119 Big Data z danymi kolumnowymi, bardzo trudno jest prze\u015bcign\u0105\u0107 H2O.<\/p>\n<p><\/p>\n<h1 id=\"tehnicheskie-chellenzhi\">Technical challenges<\/h1>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Jaki by\u0142 najwi\u0119kszy wyzwanie w Pa\u0144skiej karierze?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Czy omawiamy techniczn\u0105, czy nietechniczn\u0105 cz\u0119\u015b\u0107 pytania? Powiedzia\u0142bym, \u017ce najwi\u0119ksze wyzwania s\u0105 nietechniczne.\u00a0<br \/>\nJe\u015bli chodzi o technologiczne wyzwania, to je po prostu pokona\u0142em. Nie wiem nawet, kt\u00f3re z nich by\u0142o najwi\u0119ksze, ale by\u0142o kilka do\u015b\u0107 interesuj\u0105cych, kt\u00f3re zaj\u0119\u0142y sporo czasu i mentalnej walki. Kiedy do\u0142\u0105czy\u0142em do Sun, by\u0142em pewny, \u017ce stworz\u0119 szybki kompilator, a wielu starszych programist\u00f3w m\u00f3wi\u0142o, \u017ce mi si\u0119 to nie uda. Jednak podj\u0105\u0142em si\u0119 tego zadania, napisa\u0142em kompilator a\u017c do alokatora rejestr\u00f3w, kt\u00f3ry by\u0142 do\u015b\u0107 szybki. By\u0142 tak samo szybki jak nowoczesny C1, ale w\u00f3wczas alokator by\u0142 znacznie wolniejszy, a patrz\u0105c wstecz \u2013 to by\u0142a kwestia du\u017cej struktury danych. Potrzebowa\u0142em jej, aby napisa\u0107 graficzny alokator rejestr\u00f3w i nie rozumia\u0142em dylematu mi\u0119dzy ekspresyjno\u015bci\u0105 kodu a szybko\u015bci\u0105, co w tamtym czasie by\u0142o bardzo wa\u017cne. Okaza\u0142o si\u0119, \u017ce struktury danych cz\u0119sto przekracza\u0142y rozmiar cache'a na x86 z tamtej epoki, wi\u0119c je\u015bli pocz\u0105tkowo zak\u0142ada\u0142em, \u017ce alokator rejestr\u00f3w b\u0119dzie zajmowa\u0142 5-10 procent ca\u0142ego czasu JIT, to w rzeczywisto\u015bci wynios\u0142o to 50 procent. <\/p>\n<p><\/p>\n<p>Czas mija\u0142, kompilator stawa\u0142 si\u0119 coraz bardziej zrozumia\u0142y i wydajny, przesta\u0142 generowa\u0107 okropny kod w wielu przypadkach, a wydajno\u015b\u0107 coraz cz\u0119\u015bciej zaczyna\u0142a przypomina\u0107 to, co uzyskuje kompilator C. Oczywi\u015bcie, je\u015bli nie piszesz jakiej\u015b kiepskiej rzeczy, kt\u00f3rej nawet C nie przyspiesza. Je\u015bli piszesz kod w stylu C, uzyskujesz wydajno\u015b\u0107 na poziomie C w wi\u0119kszej liczbie przypadk\u00f3w. I im dalej, tym cz\u0119\u015bciej kod wygl\u0105da\u0142 asymptotycznie jak kod w C, alokator rejestr\u00f3w stawa\u0142 si\u0119 czym\u015b zako\u0144czonym\u2026 niezale\u017cnie od tego, czy tw\u00f3j kod dzia\u0142a\u0142 szybko, czy wolno. Wci\u0105\u017c pracowa\u0142em nad alokatorem, aby dokonywa\u0142 lepszych alokacji. Stawa\u0142 si\u0119 coraz wolniejszy, ale osi\u0105ga\u0142 coraz lepsz\u0105 wydajno\u015b\u0107 w sytuacjach, w kt\u00f3rych nikt ju\u017c nie radzi\u0142 sobie. Mog\u0142em zanurzy\u0107 si\u0119 w alokatorze rejestr\u00f3w, w\u0142o\u017cy\u0107 tam miesi\u0105c pracy, a nagle ca\u0142y kod zaczyna\u0142 dzia\u0142a\u0107 o 5% szybciej. Dzia\u0142o si\u0119 to raz po raz i alokator rejestr\u00f3w sta\u0142 si\u0119 czym\u015b na kszta\u0142t dzie\u0142a sztuki \u2013 wszyscy go kochali lub nienawidzili, a ludzie z akademii zadawali pytania dotycz\u0105ce tego, \u201edlaczego wszystko robi si\u0119 w ten spos\u00f3b\u201d, dlaczego nie. <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Register_allocation#Linear_Scan\">linijne skanowanie<\/a><\/noindex>, a jaka jest r\u00f3\u017cnica. Odpowied\u017a jest taka sama: allocator oparty na kolorowaniu grafu plus bardzo staranna praca z kodem bufora to narz\u0119dzie do zwyci\u0119stwa, najlepsza kombinacja, kt\u00f3rej nikt nie mo\u017ce pokona\u0107. To do\u015b\u0107 nieoczywista rzecz. Wszystko inne, co robi kompilator \u2013 to do\u015b\u0107 znane rzeczy, chocia\u017c r\u00f3wnie\u017c doprowadzone do poziomu sztuki. Zawsze robi\u0142em rzeczy, kt\u00f3re mia\u0142y przekszta\u0142ci\u0107 kompilator w dzie\u0142o sztuki. Ale nic z tego nie by\u0142o czym\u015b nadzwyczajnym \u2013 z wyj\u0105tkiem allocatora rejestr\u00f3w. Klucz w tym, \u017ce trzeba to robi\u0107 starannie, <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Register_allocation\">przeci\u0105\u0107<\/a><\/noindex> pod obci\u0105\u017ceniem i, je\u015bli to si\u0119 zdarza (mog\u0119 wyja\u015bni\u0107 bardziej szczeg\u00f3\u0142owo, je\u015bli to interesuj\u0105ce), oznacza to, \u017ce mo\u017cna bardziej agresywnie inline'owa\u0107, bez ryzyka przekroczenia punktu za\u0142amania wykresu wydajno\u015bci. W tamtych czasach by\u0142o mn\u00f3stwo pe\u0142noskalowych kompilator\u00f3w, obwieszonych bajerami i gwizdkami, w kt\u00f3rych by\u0142y allocatory rejestr\u00f3w, ale nikt wi\u0119cej tego nie potrafi\u0142. <\/p>\n<p><\/p>\n<p>Problem polega na tym, \u017ce je\u015bli dodasz metody, kt\u00f3re nale\u017cy inline'owa\u0107, zwi\u0119kszaj\u0105c obszar inline'u, zestaw u\u017cywanych warto\u015bci natychmiast przekracza liczb\u0119 rejestr\u00f3w, co prowadzi do spillage. Krytyczny moment zazwyczaj nast\u0119puje, gdy alokator ust\u0119puje, a jeden dobry kandydat na spillage kosztuje wi\u0119cej ni\u017c drugi, wi\u0119c spillasz zupe\u0142nie dzikie rzeczy. Warto\u015b\u0107 inline'u polega na tym, \u017ce tracisz cz\u0119\u015b\u0107 overheadu, overheadu na wywo\u0142ania i przechowywanie, mo\u017cesz widzie\u0107 warto\u015bci w \u015brodku i mo\u017cesz je dalej optymalizowa\u0107. Koszt inline'u polega na tym, \u017ce powstaje du\u017ca liczba \u017cywych warto\u015bci, a je\u015bli tw\u00f3j alokator rejestr\u00f3w spillage'uje wi\u0119cej ni\u017c to potrzebne, od razu przegrywasz. Dlatego wi\u0119kszo\u015b\u0107 alokator\u00f3w ma problem: kiedy inline przechodzi pewn\u0105 granic\u0119, wszystko wok\u00f3\u0142 zaczyna spilla\u0107, a wydajno\u015b\u0107 mo\u017cna w\u0142o\u017cy\u0107 do toalety. Ci, kt\u00f3rzy realizuj\u0105 kompilator, dodaj\u0105 pewne heurystyki: na przyk\u0142ad, aby zatrzyma\u0107 inline, zaczynaj\u0105c od pewnego wystarczaj\u0105co du\u017cego rozmiaru, poniewa\u017c alokacje wszystko psuj\u0105. Tak powstaje z\u0142amanie wykresu wydajno\u015bci \u2013 wci\u0105\u017c inline'ujesz, wydajno\u015b\u0107 powoli ro\u015bnie \u2013 a potem bam! \u2013 opada gwa\u0142townie, poniewa\u017c wykonujesz zbyt wiele inline'u. Tak to wszystko dzia\u0142a\u0142o a\u017c do pojawienia si\u0119 Javy. Java wymaga znacznie wi\u0119cej inline'u, wi\u0119c musia\u0142em uczyni\u0107 m\u00f3j alokator znacznie bardziej agresywnym, aby si\u0119 wyr\u00f3wna\u0142, a nie spada\u0142, a je\u015bli zbyt wiele inline'owa\u0142e\u015b \u2013 zaczyna spilla\u0107, ale potem i tak przychodzi moment \u201enie ma wi\u0119cej spillowania\u201d. To interesuj\u0105ce spostrze\u017cenie i przysz\u0142o do mnie po prostu znik\u0105d, nieoczywiste, ale bardzo op\u0142acalne. Zaj\u0105\u0142em si\u0119 agresywnym inline'em i to zaprowadzi\u0142o mnie w takie miejsca, gdzie wydajno\u015b\u0107 Javy i C id\u0105 w parze. S\u0105 naprawd\u0119 bliskie \u2013 mog\u0119 pisa\u0107 kod w Javie, kt\u00f3ry b\u0119dzie znacznie szybszy od kodu w C, i tym podobne, ale w \u015bredniej, w du\u017cym obrazie to wszystko jest mniej wi\u0119cej por\u00f3wnywalne. My\u015bl\u0119, \u017ce cz\u0119\u015b\u0107 tej zas\u0142ugi przypisuje si\u0119 alokatorowi rejestr\u00f3w, kt\u00f3ry pozwala mi inline'owa\u0107 maksymalnie durnie. Po prostu inline'uj\u0119 wszystko, co widz\u0119. Pytanie brzmi, czy alokator dzia\u0142a dobrze, czy wynikowy kod dzia\u0142a sensownie. To by\u0142 du\u017cy wyzwanie: zrozumie\u0107 to wszystko i sprawi\u0107, by dzia\u0142a\u0142o.<\/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>W\u0142odzimierz<\/strong>: Problemy zwi\u0105zane z alokacj\u0105 rejestr\u00f3w wydaj\u0105 si\u0119 by\u0107 tematem bez ko\u0144ca. Ciekawe, czy kiedykolwiek co\u015b, co wydawa\u0142o si\u0119 obiecuj\u0105ce, nie zrealizowa\u0142o si\u0119 w praktyce?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Oczywi\u015bcie! Alokacja rejestr\u00f3w to obszar, w kt\u00f3rym pr\u00f3bujesz zastosowa\u0107 jakie\u015b heurystyki w celu rozwi\u0105zania NP-trudnego problemu. I nigdy nie uda ci si\u0119 osi\u0105gn\u0105\u0107 idealnego rozwi\u0105zania, prawda? To po prostu niemo\u017cliwe. Zobacz, kompilacja z wyprzedzeniem \u2013 r\u00f3wnie\u017c nie dzia\u0142a idealnie. Rozmowa dotyczy \u015brednich przypadk\u00f3w. Typowej wydajno\u015bci, wi\u0119c mo\u017cna przyj\u015b\u0107 i zmierzy\u0107 co\u015b, co uwa\u017casz za dobr\u0105 typow\u0105 wydajno\u015b\u0107 \u2013 w ko\u0144cu pracujesz nad jej popraw\u0105! Alokacja rejestr\u00f3w to temat ca\u0142kowicie po\u015bwi\u0119cony wydajno\u015bci. Gdy ju\u017c masz pierwszy prototyp, kt\u00f3ry dzia\u0142a i maluje, co trzeba, rozpoczyna si\u0119 praca nad wydajno\u015bci\u0105. Nale\u017cy nauczy\u0107 si\u0119 dobrze mierzy\u0107. Dlaczego to wa\u017cne? Je\u015bli masz jasne dane, mo\u017cna przyjrze\u0107 si\u0119 r\u00f3\u017cnym obszarom i zobaczy\u0107: aha, to pomog\u0142o tutaj, ale tam wszystko si\u0119 z\u0142ama\u0142o! Pojawiaj\u0105 si\u0119 \u015bwietne pomys\u0142y, dodajesz now\u0105 heurystyk\u0119 i nagle wszystko dzia\u0142a w \u015bredniej troch\u0119 lepiej. Lub nie dzia\u0142a. Mia\u0142em mn\u00f3stwo przypadk\u00f3w, kiedy walczyli\u015bmy o pi\u0119\u0107 procent wydajno\u015bci, kt\u00f3re odr\u00f3\u017cnia\u0142y nasze rozwi\u0105zanie od poprzedniego alokatora. I za ka\u017cdym razem wygl\u0105da to tak: gdzie\u015b wygrana, gdzie\u015b przegrana. Je\u015bli masz dobre narz\u0119dzia do analizy wydajno\u015bci, mo\u017cesz znale\u017a\u0107 pomys\u0142y, kt\u00f3re przegra\u0142y i zrozumie\u0107, dlaczego. Mo\u017ce warto zostawi\u0107 wszystko jak jest, a mo\u017ce bardziej powa\u017cnie zaj\u0105\u0107 si\u0119 dba\u0142o\u015bci\u0105 o szczeg\u00f3\u0142y, lub p\u00f3j\u015b\u0107 i naprawi\u0107 co\u015b innego. To ca\u0142y zestaw rzeczy! Zrobi\u0142em ten fajny hak, ale potrzebny jest jeszcze ten, ten i ten \u2013 i dopiero ich suma daje pewne poprawki. A pojedyncze elementy mog\u0105 zawodzi\u0107. Taka jest natura pracy nad wydajno\u015bci\u0105 NP-trudnych zada\u0144.<\/p>\n<p><\/p>\n<p><strong>W\u0142odzimierz<\/strong>: Odnosi si\u0119 wra\u017cenie, \u017ce takie rzeczy jak malowanie w alokatorach to zadania ju\u017c rozwi\u0105zane. C\u00f3\u017c, dla ciebie rozwi\u0105zane, s\u0105dz\u0105c po tym, co opowiadasz, wi\u0119c czy w og\u00f3le warto\u2026<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Nie zosta\u0142a ona rozwi\u0105zana jako taka. To ty musisz przekszta\u0142ci\u0107 j\u0105 w \u201erozwi\u0105zan\u0105\u201d. Istniej\u0105 trudne zadania, kt\u00f3re trzeba rozwi\u0105zywa\u0107. Gdy to zostanie zrobione, przychodzi czas na prac\u0119 nad wydajno\u015bci\u0105. Do tej pracy nale\u017cy podchodzi\u0107 w odpowiedni spos\u00f3b \u2013 robi\u0107 benchmarki, zbiera\u0107 metryki, wyja\u015bnia\u0107 sytuacje, gdy po powrocie do poprzedniej wersji tw\u00f3j stary hack zn\u00f3w dzia\u0142a (lub odwrotnie, przestaje dzia\u0142a\u0107). I nie ust\u0119powa\u0107, a\u017c czego\u015b si\u0119 nie osi\u0105gnie. Jak ju\u017c m\u00f3wi\u0142em, je\u015bli \u015bwietne pomys\u0142y, kt\u00f3re nie wypali\u0142y, to w dziedzinie alokacji rejestr\u00f3w jest ich praktycznie niesko\u0144czono\u015b\u0107. Mo\u017cna na przyk\u0142ad czyta\u0107 publikacje naukowe. Chocia\u017c obecnie ta dziedzina zacz\u0119\u0142a si\u0119 rozwija\u0107 du\u017co wolniej i sta\u0142a si\u0119 bardziej przejrzysta ni\u017c w czasach swojej m\u0142odo\u015bci. Niemniej jednak w tej dziedzinie pracuje niesko\u0144czona liczba ludzi i warto spr\u00f3bowa\u0107 wszystkich ich pomys\u0142\u00f3w \u2013 wszystkie czekaj\u0105 na swoj\u0105 szans\u0119. I nie mo\u017cesz powiedzie\u0107, jak dobre s\u0105 te pomys\u0142y, je\u015bli ich nie wypr\u00f3bujesz. Jak dobrze integruj\u0105 si\u0119 ze wszystkim innym w twoim alokatorze, bo alokator robi wiele rzeczy, a niekt\u00f3re pomys\u0142y w twoim konkretnym alokatorze mog\u0105 nie dzia\u0142a\u0107, podczas gdy w innym z \u0142atwo\u015bci\u0105. G\u0142\u00f3wnym sposobem na wygran\u0105 dla alokatora jest wyci\u0105gni\u0119cie wolnych element\u00f3w poza g\u0142\u00f3wn\u0105 \u015bcie\u017ck\u0119 i wymuszenie podzia\u0142u wzd\u0142u\u017c granic wolnych \u015bcie\u017cek. Dlatego, je\u015bli chcesz uruchomi\u0107 GC, p\u00f3j\u015b\u0107 woln\u0105 \u015bcie\u017ck\u0105, deoptymalizowa\u0107, wyrzuci\u0107 wyj\u0105tek, wszystko w tym stylu \u2013 wiesz, \u017ce te rzeczy s\u0105 stosunkowo rzadkie. I naprawd\u0119 s\u0105 rzadkie, sprawdza\u0142em to. Robisz dodatkow\u0105 prac\u0119 i dzi\u0119ki temu znika wiele ogranicze\u0144 z tych wolnych \u015bcie\u017cek, ale to nie jest zbyt wa\u017cne, poniewa\u017c s\u0105 wolne i rzadko si\u0119 po nich chodzi. Na przyk\u0142ad wska\u017anik zerowy \u2013 nigdy si\u0119 nie zdarza, prawda? Musisz mie\u0107 kilka \u015bcie\u017cek na r\u00f3\u017cne sprawy, ale nie powinny one si\u0119 nawzajem zak\u0142\u00f3ca\u0107 na g\u0142\u00f3wnym.\u00a0<\/p>\n<p><\/p>\n<p><strong>W\u0142odzimierz<\/strong>: Co my\u015blisz o wielow\u0105tkowo\u015bci, gdy w\u0105tk\u00f3w jest od razu tysi\u0105ce? To przydatna rzecz?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Sukces GPU pokazuje, \u017ce jest ca\u0142kiem przydatna!<\/p>\n<p><\/p>\n<p><strong>W\u0142odzimierz<\/strong>: S\u0105 do\u015b\u0107 wyspecjalizowane. A co z procesorami og\u00f3lnego przeznaczenia?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: C\u00f3\u017c, to by\u0142a model biznesowy Azul. Odpowied\u017a pojawi\u0142a si\u0119 jeszcze w erze, kiedy ludzie bardzo cenili przewidywaln\u0105 wydajno\u015b\u0107. Wtedy pisanie r\u00f3wnoleg\u0142ego kodu by\u0142o do\u015b\u0107 trudne. Model kodowania H2O dobrze si\u0119 skaluj\u0119, ale nie jest to model og\u00f3lnego przeznaczenia. Chyba \u017ce jest nieco bardziej uniwersalny ni\u017c w przypadku u\u017cycia GPU. M\u00f3wimy o z\u0142o\u017cono\u015bci opracowania czego\u015b takiego czy o trudno\u015bci w jego u\u017cywaniu? Na przyk\u0142ad, interesuj\u0105c\u0105 lekcj\u0119 da\u0142 mi Azul, do\u015b\u0107 nieoczywist\u0105: ma\u0142e cache'e s\u0105 w porz\u0105dku.\u00a0<\/p>\n<p><\/p>\n<h1 id=\"samyy-bolshoy-chellenzh-v-zhizni\">The biggest challenge of life<\/h1>\n<p><\/p>\n<p><strong>W\u0142odzimierz<\/strong>: Co z nietechnicznymi wyzwaniami?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Najwi\u0119kszym wyzwaniem by\u0142o to, aby nie by\u0107\u2026 mi\u0142ym i uprzejmym w stosunku do innych. W rezultacie nieustannie znajdowa\u0142em si\u0119 w skrajnie konfliktowych sytuacjach. Takich, w kt\u00f3rych wiedzia\u0142em, \u017ce wszystko idzie \u017ale, ale nie wiedzia\u0142em, jak i\u015b\u0107 naprz\u00f3d w rozwi\u0105zywaniu tych problem\u00f3w i nie mog\u0142em sobie z nimi poradzi\u0107. Wiele d\u0142ugotrwa\u0142ych problem\u00f3w, trwaj\u0105cych dziesi\u0105tkami lat, pojawi\u0142o si\u0119 w\u0142a\u015bnie w ten spos\u00f3b. To, \u017ce w Javie s\u0105 kompilatory C1 i C2 \u2013 jest bezpo\u015brednim wynikiem tego. To, \u017ce w Javie przez ten ca\u0142y czas nie by\u0142o kompilacji wielopoziomowej \u2013 r\u00f3wnie\u017c. Oczywi\u015bcie, \u017ce potrzebowali\u015bmy takiego systemu, ale nie jest oczywiste, dlaczego go nie by\u0142o. Mia\u0142em problemy z jednym in\u017cynierem\u2026 lub grup\u0105 in\u017cynier\u00f3w. Dawno temu, kiedy zacz\u0105\u0142em pracowa\u0107 w Sun, by\u0142em\u2026 C\u00f3\u017c, nie tylko wtedy, mia\u0142em og\u00f3lnie zawsze swoje zdanie. I uwa\u017ca\u0142em za prawd\u0119, \u017ce mo\u017cna po prostu wzi\u0105\u0107 t\u0119 swoj\u0105 prawd\u0119 i powiedzie\u0107 prosto w twarz. Tym bardziej, \u017ce w wi\u0119kszo\u015bci czasu by\u0142em szokuj\u0105co prawdziwy. A je\u015bli nie podoba ci si\u0119 takie podej\u015bcie\u2026 zw\u0142aszcza gdy ewidentnie si\u0119 mylisz i robisz g\u0142upstwo\u2026 Og\u00f3lnie rzecz bior\u0105c, niewiele os\u00f3b mog\u0142o tolerancyjnie znosi\u0107 tak\u0105 form\u0119 komunikacji. Chocia\u017c niekt\u00f3rzy mogli, na przyk\u0142ad ja. Przez ca\u0142e \u017cycie kierowa\u0142em si\u0119 zasadami merytokratycznymi. Je\u015bli poka\u017cesz mi co\u015b niew\u0142a\u015bciwego, natychmiast si\u0119 odwr\u00f3c\u0119 i powiem: powiedzia\u0142e\u015b bzdur\u0119. Przy tym, oczywi\u015bcie, przepraszam i wszystko takie, doceniam zas\u0142ugi, je\u015bli takie w og\u00f3le istniej\u0105, i podejmuj\u0119 inne w\u0142a\u015bciwe dzia\u0142ania. Z drugiej strony, szokuj\u0105co cz\u0119sto jestem szokuj\u0105co prawdziwy. I to niezbyt dobrze dzia\u0142a w relacjach z lud\u017ami. Nie staram si\u0119 by\u0107 mi\u0142y, ale stawiam sprawy jasno. \u201eTo nigdy nie zadzia\u0142a, poniewa\u017c jeden, dwa i trzy\u201d. A oni na to: \u201eOjej!\u201d. By\u0142y te\u017c inne konsekwencje, kt\u00f3re lepiej pomin\u0105\u0107: na przyk\u0142ad prowadz\u0105ce do rozwodu z \u017con\u0105 i dziesi\u0119ciu lat depresji po tym.<\/p>\n<p><\/p>\n<p>Challenge to jest walka z lud\u017ami, z ich postrzeganiem tego, co mo\u017cesz lub nie mo\u017cesz robi\u0107, co jest wa\u017cne, a co nie. By\u0142o wiele wyzwa\u0144 dotycz\u0105cych stylu kodowania. Wci\u0105\u017c pisz\u0119 du\u017co kodu, a w tamtych czasach musia\u0142em nawet zwolni\u0107 tempo, poniewa\u017c zajmowa\u0142em si\u0119 zbyt wieloma r\u00f3wnoleg\u0142ymi zadaniami i robi\u0142em je \u017ale, zamiast skupi\u0107 si\u0119 na jednym. Patrz\u0105c wstecz, napisa\u0142em po\u0142ow\u0119 kodu zespo\u0142u Java JIT, zespo\u0142u C2. Nast\u0119pny najszybszy programista pisa\u0142 o po\u0142ow\u0119 wolniej, nast\u0119pny - jeszcze o po\u0142ow\u0119 wolniej, a to by\u0142 wyk\u0142adniczy spadek. Si\u00f3dma osoba w tym szeregu by\u0142a bardzo, bardzo wolna - tak ju\u017c zazwyczaj bywa! Dotkn\u0105\u0142em wielu fragment\u00f3w kodu. Obserwowa\u0142em, kto co pisze, bez wyj\u0105tku, wpatrywa\u0142em si\u0119 w ich kod, recenzowa\u0142em ka\u017cdego z nich i nadal pisa\u0142em wi\u0119cej ni\u017c kt\u00f3rykolwiek z nich. Podej\u015bcie do ludzi nie dzia\u0142a zbyt dobrze. Niekt\u00f3rzy tego nie lubi\u0105. A kiedy nie mog\u0105 sobie z tym poradzi\u0107, zaczynaj\u0105 si\u0119 rozmaite pretensje. Na przyk\u0142ad, pewnego razu powiedziano mi, \u017cebym przesta\u0142 pisa\u0107 kod, bo pisz\u0119 zbyt du\u017co, co zagra\u017ca zespo\u0142owi, a dla mnie brzmia\u0142o to jak \u017cart: cz\u0142owieku, je\u015bli ca\u0142a reszta zespo\u0142u zniknie, a ja b\u0119d\u0119 dalej pisa\u0142 kod, stracisz tylko po\u0142ow\u0119 zespo\u0142u. Z drugiej strony, je\u015bli b\u0119d\u0119 kontynuowa\u0142 pisanie kodu i ty stracisz po\u0142ow\u0119 zespo\u0142u - to brzmi jak bardzo z\u0142e zarz\u0105dzanie. Nigdy szczeg\u00f3lnie si\u0119 nad tym nie zastanawia\u0142em, nigdy o tym nie m\u00f3wi\u0142em, ale i tak by\u0142o to gdzie\u015b w mojej g\u0142owie. W zak\u0105tkach \u015bwiadomo\u015bci kr\u0119ci\u0142a si\u0119 my\u015bl: \"Czy wy wszyscy \u017cartujecie?\". Zatem najwi\u0119kszym problemem by\u0142em ja i moje relacje z lud\u017ami. Teraz rozumiem siebie du\u017co lepiej, d\u0142ugo by\u0142em liderem zespo\u0142u programist\u00f3w, a teraz m\u00f3wi\u0119 ludziom wprost: wiesz, jestem taki, jaki jestem, i musicie z tym \u017cy\u0107 \u2013 nic si\u0119 nie stanie, je\u015bli tu stan\u0119? I kiedy zacz\u0119li sobie z tym radzi\u0107, wszystko zacz\u0119\u0142o dzia\u0142a\u0107. Nie jestem ani z\u0142y, ani dobry, nie mam \u017cadnych z\u0142ych zamiar\u00f3w ani egoistycznych pragnie\u0144, to po prostu moja istota i trzeba jako\u015b z tym \u017cy\u0107.<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: Ostatnio wszyscy zacz\u0119li m\u00f3wi\u0107 o samo\u015bwiadomo\u015bci dla introwertyk\u00f3w i og\u00f3lnie o umiej\u0119tno\u015bciach spo\u0142ecznych. Co mo\u017cna na ten temat powiedzie\u0107?<\/p>\n<p><\/p>\n<p><strong>Cliff<\/strong>: Tak, to by\u0142o zrozumienie i lekcja, kt\u00f3r\u0105 wynios\u0142em z rozwodu z \u017con\u0105. Co wynios\u0142em z rozwodu \u2013 to zrozumienie siebie. W ten spos\u00f3b zacz\u0105\u0142em rozumie\u0107 innych ludzi. Zrozumie\u0107, jak ta interakcja dzia\u0142a. To doprowadzi\u0142o do odkry\u0107 jedno po drugim. Pojawi\u0142o si\u0119 \u015bwiadomo\u015b\u0107, kim jestem i co sob\u0105 reprezentuj\u0119. Co robi\u0119: albo zajmuj\u0119 si\u0119 zadaniem, albo unikam konfliktu, albo co\u015b innego \u2013 i taki poziom samo\u015bwiadomo\u015bci naprawd\u0119 pomaga utrzyma\u0107 siebie w ryzach. Po tym wszystkim idzie znacznie \u0142atwiej. Jedna rzecz, kt\u00f3r\u0105 odkry\u0142em nie tylko u siebie, ale i u innych programist\u00f3w \u2013 to niemo\u017cno\u015b\u0107 werbalizacji my\u015bli, gdy jeste\u015b w stanie emocjonalnego stresu. Na przyk\u0142ad, siedzisz i programujesz, znajdujesz si\u0119 w stanie przep\u0142ywu, a tu biegn\u0105 do ciebie i zaczynaj\u0105 krzycze\u0107 w histerii, \u017ce co\u015b si\u0119 zepsu\u0142o, a teraz b\u0119d\u0105 stosowane skrajne \u015brodki. I nie mo\u017cesz powiedzie\u0107 ani s\u0142owa, bo jeste\u015b w stanie emocjonalnego stresu. Zdobyta wiedza pozwala przygotowa\u0107 si\u0119 na ten moment, prze\u017cy\u0107 go i przej\u015b\u0107 do planu awaryjnego, po kt\u00f3rym mo\u017cna ju\u017c co\u015b zrobi\u0107. Wi\u0119c tak, gdy zaczynasz zdawa\u0107 sobie spraw\u0119, jak to wszystko dzia\u0142a \u2013 to ogromne wydarzenie, kt\u00f3re zmienia \u017cycie.\u00a0<br \/>\nSam nie mog\u0142em znale\u017a\u0107 odpowiednich s\u0142\u00f3w, ale zapami\u0119ta\u0142em sekwencj\u0119 dzia\u0142a\u0144. Istota tego jest taka, \u017ce ta reakcja \u2013 jest zar\u00f3wno fizyczna, jak i werbalna, i potrzebujesz przestrzeni. Takiej przestrzeni, w zenowskim sensie. W\u0142a\u015bnie to trzeba wyja\u015bni\u0107, a potem od razu odsun\u0105\u0107 si\u0119 na bok \u2013 czysto fizycznie si\u0119 odsun\u0105\u0107. Gdy milcz\u0119, mog\u0119 przetworzy\u0107 sytuacj\u0119 w zakresie emocji. W miar\u0119 jak adrenalina dociera do m\u00f3zgu, prze\u0142\u0105cza ci\u0119 w tryb \u201ewalcz lub uciekaj\u201d, ju\u017c nie mo\u017cesz nic powiedzie\u0107, nie \u2013 teraz jeste\u015b idiot\u0105, in\u017cynierem do bicia, niezdolnym do godnej odpowiedzi lub przynajmniej zatrzymania ataku, a atakuj\u0105cy mo\u017ce swobodnie atakowa\u0107 raz za razem. Najpierw trzeba zn\u00f3w sta\u0107 si\u0119 sob\u0105, odzyska\u0107 kontrol\u0119, wyj\u015b\u0107 z trybu \u201ewalcz lub uciekaj.\u201d <\/p>\n<p><\/p>\n<p>I oto dlatego potrzebna jest werbalna przestrze\u0144. Po prostu wolna przestrze\u0144. Je\u015bli w og\u00f3le co\u015b m\u00f3wi\u0107, mo\u017cna to w\u0142a\u015bnie zadeklarowa\u0107, a potem p\u00f3j\u015b\u0107 i naprawd\u0119 znale\u017a\u0107 sobie \"przestrze\u0144\": mo\u017cna wyj\u015b\u0107 na spacer po parku, zamkn\u0105\u0107 si\u0119 pod prysznicem \u2013 to nie ma znaczenia. Najwa\u017cniejsze jest, aby tymczasowo od\u0142\u0105czy\u0107 si\u0119 od tej sytuacji. Kiedy tylko na kilka sekund si\u0119 od\u0142\u0105cza, kontrola wraca, zaczynasz my\u015ble\u0107 trze\u017awo. \"Dobrze, nie jestem jakim\u015b idiot\u0105, nie robi\u0119 g\u0142upich rzeczy, jestem ca\u0142kiem przydatnym cz\u0142owiekiem\". Gdy tylko uda ci si\u0119 przekona\u0107 samego siebie, czas przej\u015b\u0107 do nast\u0119pnego etapu: zrozumie\u0107, co si\u0119 wydarzy\u0142o. Zosta\u0142e\u015b zaatakowany, atak przyszed\u0142 z nieoczekiwanej strony, to by\u0142a nieuczciwa, pod\u0142a zasadzka. To \u017ale. Nast\u0119pny krok to zrozumie\u0107, dlaczego atakuj\u0105cemu to by\u0142o potrzebne. Rzeczywi\u015bcie, dlaczego? Mo\u017ce dlatego, \u017ce sam jest w furii? Dlaczego jest w furii? Na przyk\u0142ad, poniewa\u017c sam si\u0119 skompromitowa\u0142 i nie mo\u017ce wzi\u0105\u0107 odpowiedzialno\u015bci? W ten spos\u00f3b trzeba ostro\u017cnie przeanalizowa\u0107 ca\u0142\u0105 sytuacj\u0119. Ale aby to zrobi\u0107, potrzebna jest przestrze\u0144 do manewru, werbalna przestrze\u0144. Pierwszy krok to zerwanie werbalnego kontaktu. Uciec od dyskusji s\u0142ownej. Odwo\u0142a\u0107 j\u0105, odej\u015b\u0107 jak najszybciej. Je\u015bli to rozmowa telefoniczna \u2013 po prostu od\u0142\u00f3\u017c s\u0142uchawk\u0119 \u2013 to umiej\u0119tno\u015b\u0107, kt\u00f3r\u0105 zdoby\u0142em podczas rozm\u00f3w z by\u0142\u0105 \u017con\u0105. Je\u015bli rozmowa nie prowadzi do niczego dobrego, po prostu m\u00f3w \"do widzenia\" i odk\u0142adaj s\u0142uchawk\u0119. Po drugiej stronie s\u0142uchawki: \"bla-bla-bla\", ty odpowiadasz: \"okej, na razie!\" i odk\u0142adasz s\u0142uchawk\u0119. Po prostu przerywasz rozmow\u0119. Pi\u0119\u0107 minut p\u00f3\u017aniej, gdy wraca do ciebie zdolno\u015b\u0107 do trze\u017awego my\u015blenia, troch\u0119 si\u0119 och\u0142adzasz, staje si\u0119 mo\u017cliwe przemy\u015blenie, co si\u0119 w\u0142a\u015bciwie sta\u0142o i co dalej. I zacz\u0105\u0107 formu\u0142owa\u0107 przemy\u015blan\u0105 odpowied\u017a, a nie tylko reagowa\u0107 emocjami. Dla mnie prze\u0142omem w samo\u015bwiadomo\u015bci by\u0142o to, \u017ce w przypadku stresu emocjonalnego nie mog\u0119 m\u00f3wi\u0107. Wyj\u015bcie z tego stanu, przemy\u015blenie i zaplanowanie, jak odpowiedzie\u0107 i zrekompensowa\u0107 problemy \u2013 oto w\u0142a\u015bciwe kroki, gdy nie mo\u017cesz m\u00f3wi\u0107. Najprostszy spos\u00f3b \u2013 uciec od sytuacji, w kt\u00f3rej manifestuje si\u0119 stres emocjonalny i po prostu przesta\u0107 w tym stresie uczestniczy\u0107. Potem odzyskujesz zdolno\u015b\u0107 do my\u015blenia, gdy mo\u017cesz my\u015ble\u0107, pojawia si\u0119 mo\u017cliwo\u015b\u0107 m\u00f3wienia, i tak dalej.<\/p>\n<p><\/p>\n<p>Przy okazji, w s\u0105dzie adwokat strony przeciwnej pr\u00f3buje to robi\u0107 z tob\u0105 \u2013 teraz ju\u017c wiadomo, dlaczego. Poniewa\u017c ma mo\u017cliwo\u015b\u0107 ci\u0119 tak przyt\u0142oczy\u0107, \u017ce nie b\u0119dziesz w stanie nawet wym\u00f3wi\u0107 swojego imienia, na przyk\u0142ad. W dos\u0142ownym sensie, nie b\u0119dziesz w stanie m\u00f3wi\u0107. Je\u015bli to si\u0119 z tob\u0105 dzieje i je\u015bli wiesz, \u017ce znajdziesz si\u0119 w miejscu, gdzie tocz\u0105 si\u0119 s\u0142owne bitwy, w miejscu takim jak s\u0105d, mo\u017cna przyj\u015b\u0107 ze swoim prawnikiem. Prawnik stanie w twojej obronie i powstrzyma s\u0142owny atak, a zrobi to w zupe\u0142nie legalny spos\u00f3b, przywracaj\u0105c ci utracon\u0105 przestrze\u0144 zen. Na przyk\u0142ad, musia\u0142em kilka razy zadzwoni\u0107 do rodziny, s\u0119dzia podszed\u0142 do tego do\u015b\u0107 przyja\u017anie, ale adwokat strony przeciwnej krzycza\u0142 i krzycza\u0142 na mnie, nie mog\u0142em nawet wtr\u0105ci\u0107 s\u0142owa. W takich sytuacjach najlepiej sprawdza si\u0119 u\u017cycie po\u015brednika. Po\u015brednik przerywa to ca\u0142e ci\u015bnienie, kt\u00f3re na ciebie nieustannie sp\u0142ywa, odkrywasz potrzebn\u0105 przestrze\u0144 zen, a wraz z ni\u0105 wraca zdolno\u015b\u0107 m\u00f3wienia. To ca\u0142a dziedzina wiedzy, w kt\u00f3rej trzeba wiele si\u0119 nauczy\u0107, wiele odkry\u0107 w sobie, a wszystko to przekszta\u0142ca si\u0119 w wysokopoziomowe decyzje strategiczne, r\u00f3\u017cne dla r\u00f3\u017cnych os\u00f3b. Niekt\u00f3rzy nie maj\u0105 opisanych powy\u017cej problem\u00f3w, zazwyczaj nie maj\u0105 ich osoby zajmuj\u0105ce si\u0119 sprzeda\u017c\u0105 zawodowo. Wszyscy ci ludzie, kt\u00f3rzy utrzymuj\u0105 si\u0119 z u\u017cywania s\u0142\u00f3w \u2013 znani piosenkarze, poeci, duchowni i politycy, zawsze maj\u0105 co\u015b do powiedzenia. Nie maj\u0105 takich problem\u00f3w, a ja je mam.<\/p>\n<p><\/p>\n<p><strong>Andrey<\/strong>: To by\u0142o\u2026 zaskakuj\u0105ce. \u015awietnie, porozmawiali\u015bmy ju\u017c ca\u0142kiem sporo i czas zako\u0144czy\u0107 ten wywiad. Na pewno spotkamy si\u0119 na konferencji i b\u0119dziemy mogli kontynuowa\u0107 ten dialog. Do zobaczenia na Hydra!<\/p>\n<p><\/p>\n<blockquote><p>Mo\u017cna kontynuowa\u0107 rozmow\u0119 z Cliffem na konferencji Hydra 2019, kt\u00f3ra odb\u0119dzie si\u0119 11-12 lipca 2019 roku w Petersburgu. Przyjedzie z wyk\u0142adem <noindex><a rel=\"nofollow\" href=\"https:\/\/hydraconf.com\/2019\/talks\/2jix5mst7iduyp9linqhfj\/?utm_source=habr&amp;utm_medium=45871\">\u201eDo\u015bwiadczenie Azul Hardware Transactional Memory\u201d<\/a><\/noindex>. Bilety mo\u017cna naby\u0107 <noindex><a rel=\"nofollow\" href=\"https:\/\/hydraconf.ru\/?utm_source=habr&amp;utm_medium=458718\">na oficjalnej stronie<\/a><\/noindex>.<\/p><\/blockquote>\n<p>\u0179r\u00f3d\u0142o: <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.1.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\/pl\/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.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\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\/pl\/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\udd47Wyj\u0105tkowy wywiad z Cliffem Clickiem \u2013 ojcem JIT-kompilacji w Java | ProHoster","description":"Cliff Click \u2014.","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/bolshoe-intervyu-s-kliffom-klikom-ottsom-jit-kompilyatsii-v-java","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","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\/pl\/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\/pl\/wp-json\/wp\/v2\/posts\/35851","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=35851"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/35851\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=35851"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=35851"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=35851"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}