Nagyszerű interjú Cliff Click-kel, a Java JIT-összeállítás atyjával

Nagyszerű interjú Cliff Click-kel, a Java JIT-összeállítás atyjávalCliff Click — A Cratus (IoT érzékelők a folyamatok fejlesztéséhez) műszaki igazgatója, számos induló vállalkozás alapítója és társalapítója (többek között a Rocket Realtime School, a Neurensic és a H2O.ai), számos sikeres kilépéssel. Cliff 15 évesen írta meg első fordítóját (Pascal a TRS Z-80-hoz)! Leginkább a C2-n végzett munkáiról ismert a Java-ban (a csomópontok tengere IR). Ez a fordító megmutatta a világnak, hogy a JIT képes kiváló minőségű kódot előállítani, ami az egyik tényező volt a Java, mint az egyik fő modern szoftverplatform megjelenésében. Ezután Cliff segített az Azul Systemsnek felépíteni egy 864 magos nagyszámítógépet, tiszta Java szoftverrel, amely 500 ezredmásodperc alatt támogatja a GC szüneteket egy 10 gigabájtos halmon. Általában Cliffnek sikerült a JVM minden aspektusán dolgozni.

 
Ez a habrapost egy nagyszerű interjú Cliff-fel. A következő témákról fogunk beszélgetni:

  • Áttérés alacsony szintű optimalizálásra
  • Hogyan készítsünk egy nagy refaktorálást
  • Költségmodell
  • Alacsony szintű optimalizálási képzés
  • Gyakorlati példák a teljesítmény javítására
  • Miért hozzon létre saját programozási nyelvet?
  • Teljesítménymérnöki karrier
  • Technikai kihívások
  • Egy kicsit a regiszterelosztásról és a többmagosról
  • A legnagyobb kihívás az életben

Az interjút készíti:

  • Andrey Satarin az Amazon Web Services-től. Karrierje során egészen más projektekben dolgozott: tesztelte a NewSQL elosztott adatbázisát a Yandexben, egy felhőérzékelő rendszert a Kaspersky Labban, egy többjátékos játékot a Mail.ru-ban és egy devizaár-számítási szolgáltatást a Deutsche Bankban. Érdekelt nagyméretű háttérrendszerek és elosztott rendszerek tesztelése.
  • Vlagyimir Szitnyikov a Netcrackertől. Tíz évnyi munka a NetCracker OS teljesítményén és méretezhetőségén, amely szoftver, amelyet a távközlési szolgáltatók használnak a hálózati és hálózati berendezések kezelési folyamatainak automatizálására. Érdekelnek a Java és az Oracle Database teljesítményével kapcsolatos problémák. Több mint egy tucat teljesítményjavítás szerzője a hivatalos PostgreSQL JDBC illesztőprogramban.

Áttérés alacsony szintű optimalizálásra

Andrew: Ön nagy név a JIT-összeállítás, a Java és általában az előadói munka világában, igaz? 

Szikla: Ez így van!

Andrew: Kezdjük néhány általános kérdéssel a teljesítménymunkával kapcsolatban. Mi a véleménye a magas és alacsony szintű optimalizációk közötti választásról, például a CPU-szinten történő munkavégzésről?

Szikla: Igen, itt minden egyszerű. A leggyorsabb kód az, amelyik soha nem fut le. Ezért mindig magas szintről kell kezdenie, algoritmusokon kell dolgoznia. A jobb O jelölés legyőzi a rosszabb O jelölést, hacsak nem lépnek közbe néhány elég nagy konstans. Az alacsony szintű dolgok utoljára maradnak. Általában, ha elég jól optimalizáltad a verem többi részét, és még mindig maradt néhány érdekesség, az alacsony szint. De hogyan lehet magas szintről indulni? Honnan tudod, hogy elég magas szintű munkát végeztek? Hát... dehogy. Nincsenek kész receptek. Meg kell értenie a problémát, el kell döntenie, hogy mit fog tenni (hogy a jövőben ne tegyen felesleges lépéseket), majd felfedheti a profilozót, amely hasznosat tud mondani. Egy ponton te magad is rájössz, hogy megszabadultál a felesleges dolgoktól, és itt az ideje egy kis finomhangolásnak. Ez határozottan egy különleges művészet. Sokan csinálnak felesleges dolgokat, de olyan gyorsan mozognak, hogy nincs idejük a termelékenység miatt aggódni. De ez addig van, amíg a kérdés egyenesen fel nem merül. Általában az esetek 99%-ában senkit nem érdekel, hogy mit csinálok, egészen addig a pillanatig, amikor egy fontos dolog nem jön a kritikus úton, ami senkit sem érdekel. És itt mindenki nyaggatni kezd, hogy „miért nem működött tökéletesen a kezdetektől fogva”. Általában mindig van mit javítani a teljesítményen. De az esetek 99%-ában nincs leadod! Csak próbálsz valamit működésre bírni, és közben rájössz, mi a fontos. Soha nem tudhatod előre, hogy ennek a darabnak tökéletesnek kell lennie, így tulajdonképpen mindenben tökéletesnek kell lenni. De ez lehetetlen, és nem teszed meg. Mindig sok mindent meg kell javítani – és ez teljesen normális.

Hogyan készítsünk egy nagy refaktorálást

Andrew: Hogyan dolgozol egy előadáson? Ez egy átfogó probléma. Például, kellett valaha olyan problémákon dolgoznia, amelyek sok létező funkció kereszteződéséből adódnak?

Szikla: Igyekszem elkerülni. Ha tudom, hogy probléma lesz a teljesítménnyel, gondolok rá, mielőtt elkezdem a kódolást, különösen az adatstruktúrák esetében. De gyakran csak később fedezi fel mindezt. És akkor szélsőséges intézkedésekre kell menni, és meg kell tenni azt, amit én „újraír és hódít”: meg kell ragadnia egy elég nagy darabot. A kód egy részét még mindig át kell írni teljesítményproblémák vagy valami más miatt. Bármi legyen is a kód átírásának oka, szinte mindig jobb egy nagyobb darabot átírni, mint egy kisebbet. Ebben a pillanatban mindenki remegni kezd a félelemtől: „Úristen, ennyi kódhoz nem nyúlhat!” De valójában ez a megközelítés szinte mindig sokkal jobban működik. Azonnal fel kell vállalnia egy nagy problémát, körbe kell rajzolnia egy nagy kört, és azt kell mondania: mindent átírok a körön belül. A szegély sokkal kisebb, mint a benne lévő tartalom, amit cserélni kell. És ha a határok ilyen kirajzolása lehetővé teszi, hogy tökéletesen végezze el a belső munkát, szabad a keze, tegyen, amit akar. Miután megértette a problémát, az újraírási folyamat sokkal könnyebbé válik, ezért harapjon egy nagyot!
Ugyanakkor, amikor nagy átírást hajt végre, és rájön, hogy a teljesítmény problémát jelent, azonnal elkezdhet aggódni miatta. Ez általában olyan egyszerű dolgokká válik, mint például: „ne másoljon adatokat, kezelje az adatokat a lehető legegyszerűbben, legyen kicsi”. A nagy átírásoknál szabványos módszerek vannak a teljesítmény javítására. És szinte mindig az adatok körül forognak.

Költségmodell

Andrew: Az egyik podcastban a költségmodellekről beszélt a termelékenység összefüggésében. Elmagyaráznád, hogy mit értesz ez alatt?

Szikla: Természetesen. Olyan korban születtem, amikor a processzor teljesítménye rendkívül fontos volt. És ez a korszak újra visszatér - a sors nem nélkülözi az iróniát. A nyolcbites gépek idejét kezdtem élni, az első számítógépem 256 bájttal működött. Pontosan bájtok. Minden nagyon kicsi volt. Számolni kellett az utasításokat, és ahogy elkezdtük feljebb lépni a programozási nyelvek között, a nyelvek egyre jobban elfoglalták a helyüket. Ott volt az Assembler, aztán a Basic, majd a C, és a C sok részletről gondoskodott, mint például a regiszterkiosztás és az utasítások kiválasztása. De ott minden teljesen világos volt, és ha mutatok egy változó példányát, akkor terhelést kapok, és ennek az utasításnak az ára ismert. A hardver bizonyos számú gépi ciklust állít elő, így a különböző dolgok végrehajtási sebessége egyszerűen kiszámítható az összes futtatni kívánt utasítás összeadásával. Minden összehasonlítás/teszt/elágazás/hívás/betöltés/üzlet összeadható, és azt mondhatnánk: ez a végrehajtási idő az Ön számára. Amikor a teljesítmény javításán dolgozik, feltétlenül figyeljen arra, hogy milyen számok felelnek meg a kis meleg ciklusoknak. 
De amint áttérsz Java-ra, Pythonra és hasonló dolgokra, nagyon gyorsan eltávolodsz az alacsony szintű hardvertől. Mennyibe kerül egy getter hívása Java nyelven? Ha a JIT a HotSpotban helyes beépített, akkor betöltődik, de ha ezt nem tette meg, akkor függvényhívás lesz. Mivel a hívás forró hurkon történik, felülírja az összes többi optimalizálást a hurokban. Ezért a valós költség sokkal magasabb lesz. És azonnal elveszíti a képességét, hogy megnézzen egy kódrészletet, és megértse, hogy azt a processzor órajele, a memória és a gyorsítótár tekintetében kell végrehajtanunk. Mindez csak akkor válik érdekessé, ha igazán belevágsz az előadásba.
Most olyan helyzetben találjuk magunkat, hogy a processzor sebessége alig nőtt egy évtizede. A régi idők visszatértek! Már nem számíthat jó egyszálú teljesítményre. De ha hirtelen belevágsz a párhuzamos számítástechnikába, az hihetetlenül nehéz, mindenki úgy néz rád, mint James Bondra. A tízszeres gyorsulások általában olyan helyeken jelentkeznek, ahol valaki valamit elrontott. Az egyidejűség sok munkát igényel. A XNUMX-szeres gyorsulás eléréséhez meg kell értened a költségmodellt. Mi és mennyibe kerül? És ehhez meg kell értenie, hogy a nyelv hogyan illeszkedik a mögöttes hardverhez.
Martin Thompson remek szót választott blogjához Mechanikus szimpátia! Meg kell értenie, hogy a hardver mit fog csinálni, pontosan hogyan fogja megtenni, és egyáltalán miért csinálja azt, amit. Ennek segítségével meglehetősen könnyű elkezdeni számolni az utasításokat, és kitalálni, hogy hol tart a végrehajtási idő. Ha nem rendelkezik megfelelő képzettséggel, csak egy fekete macskát keres egy sötét szobában. Olyan embereket látok, akik folyamatosan optimalizálják a teljesítményt, és fogalmuk sincs, mit csinálnak. Sokat szenvednek, és nem sokat fejlődnek. És amikor előveszem ugyanazt a kódrészletet, becsúsztam néhány apró hackelést, és ötszörösére vagy tízszeresére gyorsítom, akkor azt mondják: hát ez nem fair, már tudtuk, hogy jobb vagy. Elképesztő. Miről beszélek... a költségmodell arról szól, hogy milyen kódot írsz és milyen gyorsan fut átlagosan a nagy képben.

Andrew: És hogy lehet ilyen hangerőt a fejedben tartani? Ez több tapasztalattal elérhető, vagy? Honnan származik az ilyen tapasztalat?

Szikla: Nos, nem a legkönnyebben szereztem a tapasztalataimat. Az Assemblyben még akkoriban programoztam, amikor minden egyes utasítást megérthettél. Hülyén hangzik, de azóta mindig a fejemben, az emlékezetemben maradt a Z80 utasításkészlet. Nem emlékszem az emberek nevére egy percen belül a beszélgetés után, de emlékszem a 40 évvel ezelőtt írt kódra. Vicces, úgy néz ki, mint egy szindróma."idióta tudós".

Alacsony szintű optimalizálási képzés

Andrew: Van egyszerűbb bejutni?

Szikla: Igen és nem. Az általunk használt hardver nem sokat változott az idők során. Mindenki x86-ot használ, az Arm okostelefonok kivételével. Ha nem valamiféle kemény beágyazást csinál, akkor ugyanezt csinálja. Oké, következő. Az utasítások sem változtak évszázadok óta. Menned kell, és írnod ​​kell valamit az Assembly-be. Nem sok, de elég ahhoz, hogy megértsük. Mosolyogsz, de én teljesen komolyan beszélek. Meg kell értenie a nyelv és a hardver közötti megfelelést. Utána menned kell írni egy kicsit, és készíteni egy kis játékfordítót egy kis játéknyelvhez. A játékszerűség azt jelenti, hogy ésszerű időn belül kell elkészíteni. Lehet szuper egyszerű, de utasításokat kell generálnia. Az utasítás generálása segít megérteni a mindenki által írt magas szintű kód és a hardveren futó gépi kód közötti híd költségmodelljét. Ez a levelezés a fordítóprogram írásakor beleég az agyba. Még a legegyszerűbb fordító is. Utána elkezdhetjük nézni a Java-t és azt, hogy a szemantikai szakadéka sokkal mélyebb, és sokkal nehezebb hidakat építeni felette. Jáván sokkal nehezebb megérteni, hogy a hídunk jó vagy rossz lett, mitől fog szétesni és mi nem. De szüksége van valamiféle kiindulási pontra, ahol megnézi a kódot, és megérti: "igen, ezt a gettert minden alkalommal be kell illeszteni." Aztán kiderül, hogy néha ez megtörténik, kivéve azt a helyzetet, amikor a metódus túl nagy lesz, és a JIT elkezd mindent beilleszteni. Az ilyen helyek teljesítménye azonnal megjósolható. A getterek általában jól működnek, de aztán megnézed a nagy forró hurkokat, és rájössz, hogy vannak olyan függvényhívások, amelyek nem tudják, mit csinálnak. Ez a probléma a getterek széles körben elterjedt használatával, amiért nem szerepelnek benne, hogy nem világos, hogy getter-e. Ha van egy szuper kicsi kódbázisa, egyszerűen emlékezhet rá, majd azt mondja: ez egy getter, ez pedig egy setter. Egy nagy kódbázisban minden függvény a saját történetét éli, amit általában senki sem ismer. A profilkészítő azt mondja, hogy az idő 24%-át elvesztettük valamilyen hurkon, és ahhoz, hogy megértsük, mit csinál ez a ciklus, meg kell vizsgálnunk minden egyes funkciót belül. Ezt nem lehet megérteni a funkció tanulmányozása nélkül, és ez komolyan lelassítja a megértés folyamatát. Ezért nem használok gettereket és settereket, új szintre léptem!
Hol lehet beszerezni a költségmodellt? Hát persze, lehet olvasni valamit... De szerintem a legjobb módszer a cselekvés. Egy kis fordítóprogram készítése a legjobb módja annak, hogy megértse a költségmodellt, és beillessze a saját fejébe. Kezdő dolga egy kis fordító, ami alkalmas lenne mikrohullámú sütő programozására. Nos, úgy értem, ha már rendelkezik programozási ismeretekkel, akkor az elég lesz. Mindezek a dolgok, mint például egy olyan karakterlánc elemzése, amely valamilyen algebrai kifejezésként van birtokában, a matematikai műveletek utasításainak kinyerése onnan a megfelelő sorrendben, a megfelelő értékek vétele a regiszterekből - mindez egyszerre történik. És miközben ezt csinálod, ez bevésődik az agyadba. Szerintem mindenki tudja, mit csinál a fordító. Ez pedig megértheti a költségmodellt.

Gyakorlati példák a teljesítmény javítására

Andrew: Mire kell még figyelni, ha a termelékenységen dolgozik?

Szikla: Adatstruktúrák. Egyébként igen, már régóta nem tanítottam ezeket az órákat... Rakétaiskola. Jó móka volt, de sok erőfeszítést igényelt, és nekem is van életem! RENDBEN. Így az egyik nagy és érdekes órán, a „Hová megy a teljesítményed” egy példát adtam a diákoknak: két és fél gigabájt fintech adatot olvastak ki egy CSV-fájlból, majd ki kellett számolniuk az eladott termékek számát. . Rendszeres kullancspiaci adatok. A 70-es évek óta szöveges formátumba konvertált UDP-csomagok. Chicago Mercantile Exchange – mindenféle dolog, mint a vaj, kukorica, szójabab, ilyesmi. Számolni kellett ezeket a termékeket, a tranzakciók számát, a pénzeszközök és áruk átlagos mozgási volumenét stb. Ez elég egyszerű kereskedési matematika: keresse meg a termékkódot (ez 1-2 karakter a hash táblázatban), szerezze be az összeget, adja hozzá az egyik kereskedési készlethez, adjon hozzá mennyiséget, adjon hozzá értéket és még néhány dolgot. Nagyon egyszerű matematika. A játék megvalósítása nagyon egyszerű volt: minden egy fájlban van, én beolvasom a fájlt és haladok benne, az egyes rekordokat Java karakterláncokra osztom, keresem bennük a szükséges dolgokat és a fent leírt matematika szerint összeadom. És kis sebességgel működik.

Ezzel a megközelítéssel nyilvánvaló, hogy mi történik, és a párhuzamos számítástechnika nem segít, igaz? Kiderült, hogy a teljesítmény ötszörösére növelhető pusztán a megfelelő adatszerkezetek kiválasztásával. És ez még tapasztalt programozókat is meglep! Az én konkrét esetemben a trükk az volt, hogy nem szabad forró hurokban memóriafoglalásokat végrehajtani. Nos, ez nem a teljes igazság, de általában - nem szabad kiemelni az „egyszer X-ben” kifejezést, ha X elég nagy. Ha X két és fél gigabájt, akkor ne rendeljen hozzá semmit „betűnként egyszer”, „soronként egyszer”, vagy „mezőnként egyszer”, semmi ehhez hasonló. Itt telik az idő. Ez egyáltalán hogy működik? Képzeld el, hogy telefonálok String.split() vagy BufferedReader.readLine(). Readline egy karakterláncot hoz létre a hálózaton keresztül érkező bájtok halmazából, minden sorhoz egyszer, a több száz millió sor mindegyikéhez. Fogom ezt a sort, elemzem és kidobom. Miért dobom el - nos, már feldolgoztam, ez minden. Tehát ezekből a 2.7G-ből kiolvasott bájtonként két karakter kerül a sorba, vagyis már 5.4G, és semmire sincs szükségem tovább, szóval kidobják. Ha a memória sávszélességét nézzük, akkor a processzorban a memórián és a memóriabuszon átmenő 2.7G-t töltünk be, majd kétszer annyit küldenek a memóriában heverő sorra, és mindez minden új sor keletkezésekor elkopik. De el kell olvasnom, a hardver olvassa, még akkor is, ha később minden kopott. És le kell írnom, mert létrehoztam egy sort, és a gyorsítótárak megteltek - a gyorsítótár nem tud 2.7G-t befogadni. Tehát minden olvasott bájt után még két bájtot olvasok, és még két bájtot írok, és a végén 4:1 arányuk van - ebben az arányban pazaroljuk a memória sávszélességét. Aztán kiderül, hogy ha megteszem String.split() – nem utoljára csinálom, lehet még 6-7 mező belül. Tehát a klasszikus CSV-kód beolvasása, majd a karakterláncok elemzése körülbelül 14:1-es memória sávszélesség-pazarlást eredményez ahhoz képest, amit valójában szeretne. Ha kidobja ezeket a válogatásokat, ötszörös sebességet kaphat.

És ez nem is olyan nehéz. Ha megfelelő szögből nézi a kódot, minden egészen egyszerűvé válik, amint rájön a probléma. Nem szabad teljesen abbahagyni a memóriafoglalást: csak az a probléma, hogy lefoglalsz valamit, és az azonnal meghal, és közben eléget egy fontos erőforrást, ami jelen esetben a memória sávszélessége. Mindez pedig a termelékenység csökkenését eredményezi. Az x86-on általában aktívan kell égetni a processzorciklusokat, de itt sokkal korábban égetett el minden memória. A megoldás a váladék mennyiségének csökkentése. 
A probléma másik része az, hogy ha futtatod a profilozót, amikor a memóriacsík kifogy, pont akkor, amikor ez megtörténik, akkor általában arra vársz, hogy a gyorsítótár visszatérjen, mert tele van szeméttel, amit most előállítottál, az összes sor. Ezért minden betöltés vagy tárolási művelet lelassul, mert gyorsítótár kihagyáshoz vezet – az egész gyorsítótár lassúvá vált, és arra vár, hogy a szemét elhagyja. Ezért a profilkészítő csak meleg véletlenszerű zajt jelenít meg a teljes hurkon keresztül - nem lesz külön forró utasítás vagy hely a kódban. Csak zaj. És ha megnézzük a GC ciklusokat, mindegyik fiatal generációs és szupergyors – maximum mikro- vagy ezredmásodperc. Végül is ez az emlék azonnal elhal. Kiosztasz több milliárd gigabájtot, és ő levágja, levágja, és újra vágja. Mindez nagyon gyorsan megtörténik. Kiderült, hogy vannak olcsó GC ciklusok, meleg zaj a teljes ciklusban, de szeretnénk 5-szörös gyorsulást elérni. Ebben a pillanatban valaminek be kellene zárnia a fejedben, és megszólalnia: "miért van ez?!" A memóriasáv túlcsordulása nem jelenik meg a klasszikus hibakeresőben; futtassa a hardverteljesítmény-számláló hibakeresőt, és meg kell néznie saját maga és közvetlenül. De ez ebből a három tünetből közvetlenül nem sejthető. A harmadik tünet az, amikor megnézed, mit emelsz ki, megkérdezed a profilkészítőt, és ő azt válaszolja: "Egymilliárd sort csináltál, de a GC ingyen működött." Amint ez megtörténik, rájössz, hogy túl sok objektumot hoztál létre, és elégetted az egész memóriasávot. Van mód ennek kiderítésére, de ez nem egyértelmű. 

A probléma az adatszerkezetben van: a csupasz struktúra, ami minden történés mögött áll, túl nagy, 2.7G van a lemezen, ezért nagyon nem kívánatos erről a dologról másolatot készíteni - azonnal be akarja tölteni a hálózati bájtpufferből a regiszterekbe, nehogy ötször oda-vissza írjon-olvassunk. Sajnos a Java alapértelmezés szerint nem ad ilyen könyvtárat a JDK részeként. De ez triviális, nem? Lényegében 5-10 sornyi kódról van szó, amelyet a saját pufferelt karakterlánc-betöltő megvalósítására használunk fel, amely megismétli a karakterlánc-osztály viselkedését, miközben egy burkoló az alapul szolgáló bájtpuffer körül. Ennek eredményeként kiderül, hogy szinte úgy dolgozol, mintha karakterláncokkal dolgoznál, de valójában a pufferre mutató mutatók ott mozognak, és a nyers bájtok nem másolódnak sehova, és így ugyanazok a pufferek újra és újra felhasználódnak, és az operációs rendszer szívesen vállalja magára azokat a dolgokat, amelyekre tervezték, mint például ezeknek a bájtpuffereknek a rejtett dupla pufferelése, és Ön többé nem őröli a szükségtelen adatok végtelen folyamát. Amúgy érted, hogy a GC-vel való munka során garantált, hogy az utolsó GC ciklus után minden memóriafoglalás nem lesz látható a processzor számára? Ezért mindez nem lehet a gyorsítótárban, és akkor 100%-ban garantált kihagyás következik be. Amikor mutatóval dolgozunk, x86-on egy regiszter kivonása a memóriából 1-2 óraciklust vesz igénybe, és amint ez megtörténik, fizet, fizet, fizet, mert a memória be van kapcsolva. KILENC gyorsítótár – és ez a memóriafoglalás költsége. Valódi érték.

Más szóval, az adatstruktúrákat a legnehezebb megváltoztatni. És ha egyszer rájössz, hogy rossz adatstruktúrát választottál, ami a későbbiekben rontja a teljesítményt, általában sok a tennivaló, de ha nem teszed, a dolgok rosszabbra fordulnak. Először is az adatstruktúrákon kell gondolkodni, ez fontos. A fő költség itt a zsíros adatstruktúrákra esik, amelyeket a következő stílusban kezdenek használni: „Az X adatstruktúrát átmásoltam az Y adatstruktúrába, mert jobban szeretem Y alakját”. De a másolási művelet (ami olcsónak tűnik) valójában a memória sávszélességét pazarolja, és itt van eltemetve az összes elvesztegetett végrehajtási idő. Ha van egy óriási JSON-sztringem, és azt POJO-k strukturált DOM-fájává akarom alakítani, akkor a karakterlánc elemzése és a POJO felépítése, majd később a POJO ismételt elérése szükségtelen költségekkel jár – ez nem olcsó. Kivéve, ha sokkal gyakrabban szaladgálsz a POJO-k körül, mint egy karakterlánc körül. Ehelyett megpróbálhatja visszafejteni a karakterláncot, és csak azt kinyerheti ki, amire szüksége van, anélkül, hogy POJO-vá alakítaná. Ha mindez olyan úton történik, ahonnan maximális teljesítményre van szükség, nincs POJO az Ön számára, akkor valahogy közvetlenül bele kell ásni a sort.

Miért hozzon létre saját programozási nyelvet?

Andrew: Azt mondtad, hogy a költségmodell megértéséhez meg kell írni a saját kis nyelvedet...

Szikla: Nem nyelv, hanem fordító. A nyelv és a fordító két különböző dolog. A legfontosabb különbség a fejedben van. 

Andrew: Egyébként ha jól tudom, saját nyelvek létrehozásával kísérletezel. Miért?

Szikla: Mert megtehetem! Félig nyugdíjas vagyok, így ez a hobbim. Egész életemben mások nyelvét alkalmaztam. Sokat dolgoztam a kódolási stílusomon is. És azért is, mert problémákat látok más nyelvekben. Úgy látom, vannak jobb módszerek is az ismert dolgokra. És én használnám őket. Elegem van abból, hogy problémákat lássak magamban, Java-ban, Pythonban vagy bármilyen más nyelven. A React Native-ben, a JavaScript-ben és az Elm-ben most hobbiként írok, ami nem a nyugdíjról szól, hanem az aktív munkáról. Pythonban is írok, és valószínűleg továbbra is a gépi tanuláson fogok dolgozni Java háttérrendszerekhez. Sok népszerű nyelv létezik, és mindegyiknek van érdekessége. Mindenki jó a maga módján, és megpróbálhatja összehozni ezeket a funkciókat. Tehát olyan dolgokat tanulmányozom, amelyek érdekelnek, a nyelv viselkedését, és próbálok ésszerű szemantikát találni. És eddig sikerrel járok! Jelenleg a memória szemantikával küszködök, mert azt akarom, hogy olyan legyen, mint a C-ben és a Java-ban, valamint egy erős memóriamodellt és memóriaszemantikát a betöltésekhez és tárolásokhoz. Ugyanakkor legyen automatikus típuskövetkeztetés, mint a Haskellben. Itt megpróbálom keverni a Haskell-szerű típusú következtetést a memóriamunkával C-ben és Java-ban egyaránt. Én például ezt csinálom az elmúlt 2-3 hónapban.

Andrew: Ha olyan nyelvet építesz, amely jobb szempontokat vesz át más nyelvekből, gondolod, hogy valaki az ellenkezőjét fogja tenni: átveszi az ötleteit és felhasználja azokat?

Szikla: Pontosan így jelennek meg az új nyelvek! Miért hasonlít a Java a C-hez? Mert a C-nek jó szintaxisa volt, amit mindenki értett, a Java-t pedig ez a szintaxis ihlette, hozzáadva a típusbiztonságot, a tömbhatárok ellenőrzését, a GC-t, és néhány dolgot javítottak is a C-ből. Hozzáadták a sajátjukat. De nagyon sok ihletet kaptak, igaz? Mindenki azoknak az óriásoknak a vállán áll, akik előtted jöttek – így történik a haladás.

Andrew: Ha jól értem, a nyelved memóriabiztos lesz. Gondolt már valami olyan megvalósításra, mint egy kölcsönellenőrző a Rusttól? Nézted már, mi a véleményed róla?

Szikla: Nos, én már évek óta írok C-t, ezzel a sok malloc-val és ingyenesen, és manuálisan kezelem az élettartamot. Tudja, a manuálisan vezérelt élettartam 90-95%-a azonos szerkezetű. És nagyon-nagyon fájdalmas kézzel csinálni. Szeretném, ha a fordító egyszerűen elmondaná, mi folyik ott, és mit ért el a tetteivel. Egyes esetekben a kölcsönellenőrző ezt a dobozból kiveszi. És automatikusan megjelenítenie kell az információkat, mindent meg kell értenie, és még csak nem is terhelnie kell ennek a megértésnek a bemutatásával. Legalább helyi menekülési elemzést kell végeznie, és csak ha nem sikerül, akkor hozzá kell adnia az élettartamot leíró típusjegyzeteket - és egy ilyen séma sokkal összetettebb, mint egy kölcsön-ellenőrző, vagy akármelyik meglévő memóriaellenőrző. A „minden rendben” és a „nem értek semmit” közötti választás - nem, kell valami jobb. 
Szóval, mint valaki, aki sok kódot írt C nyelven, úgy gondolom, hogy az automatikus élettartam-vezérlés támogatása a legfontosabb. Elegem van abból is, hogy a Java mennyi memóriát használ, és a fő panasz a GC. Amikor memóriát foglal le Java-ban, nem kapja vissza azt a memóriát, amely az utolsó GC-ciklusban helyi volt. Ez nem így van a precízebb memóriakezeléssel rendelkező nyelveken. Ha a malloc-ot hívja, azonnal megkapja azt a memóriát, amelyet általában használt. Általában néhány ideiglenes dolgot csinál a memóriával, és azonnal visszaküldi. És azonnal visszatér a malloc készletbe, és a következő malloc ciklus újra kihúzza. Ezért a tényleges memóriahasználat az adott időpontban élő objektumok halmazára csökken, plusz a szivárgásokra. És ha minden nem teljesen illetlen módon szivárog, a memória nagy része a gyorsítótárakba és a processzorba kerül, és gyorsan működik. De sok manuális memóriakezelést igényel malloc és ingyenes hívások a megfelelő sorrendben, a megfelelő helyen. A Rust ezt önmagában is megfelelően tudja kezelni, és sok esetben még jobb teljesítményt nyújt, mivel a memóriafelhasználás az aktuális számításra leszűkítve – ahelyett, hogy a következő GC-ciklusra várnánk, hogy felszabadítsa a memóriát. Ennek eredményeként egy nagyon érdekes módszert kaptunk a teljesítmény javítására. És elég erős – úgy értem, ilyen dolgokat csináltam, amikor adatokat dolgoztam fel a fintech számára, és ez lehetővé tette, hogy körülbelül ötszörös sebességet kapjak. Ez elég nagy lökést jelent, különösen egy olyan világban, ahol a processzorok nem gyorsulnak, és még mindig várunk a fejlesztésekre.

Teljesítménymérnöki karrier

Andrew: A karrierről általánosságban is szeretnék kérdezni. Ön a HotSpotnál végzett JIT-munkájával került előtérbe, majd az Azulhoz költözött, amely szintén egy JVM-cég. De már akkor is többet dolgoztunk hardveren, mint szoftveren. Aztán hirtelen áttértek a Big Data-ra és a gépi tanulásra, majd a csalások felderítésére. Hogy történt ez? Ezek nagyon különböző fejlesztési területek.

Szikla: Elég régóta programozom, és sok különböző órát sikerült elvégeznem. És amikor az emberek azt mondják: „Ó, te vagy az, aki JIT-t csinált a Java számára!”, az mindig vicces. De előtte a PostScript klónján dolgoztam – azon a nyelven, amelyet az Apple egykor a lézernyomtatóihoz használt. És előtte elkészítettem a Forth nyelv implementációját. Azt hiszem, a közös téma számomra az eszközfejlesztés. Egész életemben olyan eszközöket készítettem, amelyekkel mások remek programjaikat írják. De részt vettem operációs rendszerek, illesztőprogramok, kernelszintű hibakeresők, operációs rendszer-fejlesztési nyelvek fejlesztésében is, ami kezdetben triviális volt, de idővel egyre bonyolultabbá vált. De a fő téma továbbra is az eszközök fejlesztése. Életem nagy része az Azul és a Sun között telt el, és a Java-ról volt szó. De amikor belevágtam a Big Data és a gépi tanulásba, visszatettem a díszes kalapomat, és azt mondtam: „Ó, most van egy nem triviális problémánk, és sok érdekes dolog történik, és az emberek csinálnak dolgokat.” Ez egy nagyszerű fejlődési út.

Igen, nagyon szeretem az elosztott számítástechnikát. Az első munkám C-s diákként volt, egy reklámprojektben. Ezt Zilog Z80 chipeken elosztott számítási módszerrel végezték, amelyek analóg OCR-hez gyűjtöttek adatokat, és amelyeket egy valódi analóg analizátor állított elő. Menő és teljesen őrült téma volt. De voltak gondok, egy részt nem ismertek fel megfelelően, ezért ki kellett venni egy képet és megmutatni egy olyan embernek, aki már tudott olvasni a szemével, és beszámolt róla, és ezért voltak adatokkal ellátott munkák, és ezek a munkák saját nyelvük volt. Volt egy háttérprogram, ami mindezt feldolgozta - a Z80-asok párhuzamosan futottak vt100-as terminálokkal - személyenként egy, és volt egy párhuzamos programozási modell a Z80-on. Néhány közös memória, amelyet az összes Z80 megoszt egy csillag konfiguráción belül; A hátlap is megosztott volt, a RAM fele pedig a hálózaton belül, másik fele pedig privát volt, vagy másra ment. Értelmesen összetett párhuzamos elosztott rendszer megosztott... félig megosztott memóriával. Mikor volt ez... nem is emlékszem, valahol a 80-as évek közepén. Elég régen. 
Igen, tegyük fel, hogy 30 év elég régen van. Az elosztott számítástechnikával kapcsolatos problémák meglehetősen régóta léteznek, az emberek régóta háborúznak Beowulf- klaszterek. Az ilyen klaszterek úgy néznek ki, mint... Például: van Ethernet és a gyors x86-od ehhez az Ethernethez van csatlakoztatva, és most hamis megosztott memóriát akarsz szerezni, mert akkor senki nem tudott elosztott számítási kódolást csinálni, túl nehéz volt és ezért ott hamis megosztott memória védelmi memória lapokkal x86-on, és ha erre az oldalra írt, akkor azt mondtuk a többi processzornak, hogy ha hozzáférnek ugyanahhoz a megosztott memóriához, akkor azt Öntől kell betölteni, és így valami olyan protokollt kell támogatni. megjelent a gyorsítótár koherenciája és ehhez szoftver. Érdekes koncepció. Az igazi probléma természetesen más volt. Mindez működött, de hamar teljesítményproblémák keletkeztek, mert senki sem értette elég jó szinten a teljesítménymodelleket - milyen memóriaelérési minták vannak, hogyan lehet megbizonyosodni arról, hogy a csomópontok ne pingálják egymást a végtelenségig, stb.

A H2O-ban arra jutottam, hogy maguk a fejlesztők felelősek annak meghatározásáért, hogy hol van elrejtve a párhuzamosság és hol nem. Kidolgoztam egy kódolási modellt, amely könnyűvé és egyszerűvé tette a nagy teljesítményű kód írását. De lassan futó kódot írni nehéz, rosszul fog kinézni. Komolyan meg kell próbálnia lassú kódot írni, nem szabványos módszereket kell használnia. A fékkód első pillantásra látható. Ebből kifolyólag általában olyan kódot írunk, ami gyorsan fut, de ki kell találni, mit kell tenni osztott memória esetén. Mindez nagy tömbökhöz van kötve, és ott a viselkedés hasonló a nem felejtő nagy tömbökhöz a párhuzamos Java-ban. Úgy értem, képzeld el, hogy két szál ír egy párhuzamos tömbbe, az egyik nyer, a másik ennek megfelelően veszít, és nem tudod, melyik melyik. Ha nem változékonyak, akkor a sorrend tetszés szerinti lehet – és ez nagyon jól működik. Az embereket nagyon érdekli a műveletek sorrendje, a volatilit a megfelelő helyre teszik, és a memóriával kapcsolatos teljesítményproblémákat a megfelelő helyre várják. Ellenkező esetben egyszerűen írnának kódot 1-től N-ig tartó hurkok formájában, ahol N néhány billió, abban a reményben, hogy minden összetett eset automatikusan párhuzamos lesz – és ott ez nem működik. De a H2O-ban ez nem a Java és nem a Scala; ha akarja, tekintheti „Java mínusz mínusz”-nak. Ez egy nagyon világos programozási stílus, és hasonló az egyszerű C- vagy Java-kód írásához hurkokkal és tömbökkel. De ugyanakkor a memória terabájtokban is feldolgozható. Még mindig H2O-t használok. Időnként használom különböző projektekben – és még mindig ez a leggyorsabb, több tucatszor gyorsabb a versenytársainál. Ha a Big Data-t oszlopos adatokkal végzi, nagyon nehéz legyőzni a H2O-t.

Technikai kihívások

Andrew: Mi volt a legnagyobb kihívásod egész pályafutásod során?

Szikla: A kérdés technikai vagy nem műszaki részét tárgyaljuk? Azt mondanám, hogy a legnagyobb kihívások nem technikaiak. 
Ami a technikai kihívásokat illeti. Egyszerűen legyőztem őket. Nem is tudom, mi volt a legnagyobb, de volt néhány elég érdekes, amihez elég sok idő kellett, mentális küzdelem. Amikor elmentem a Sunhoz, biztos voltam benne, hogy csinálok egy gyors fordítót, és egy csomó idős azt válaszolta, hogy soha nem fog sikerülni. De ezt az utat követtem, leírtam egy fordítót a regiszterelosztóba, és elég gyors volt. Olyan gyors volt, mint a modern C1, de az allokátor akkoriban sokkal lassabb volt, és utólag visszagondolva ez egy nagy adatszerkezeti probléma volt. Szükségem volt rá egy grafikus regiszterelosztó írásához, és nem értettem a kódexpresszivitás és a sebesség közötti dilemmát, ami abban a korszakban létezett és nagyon fontos volt. Kiderült, hogy az adatstruktúra általában meghaladja az akkori x86-os gyorsítótár méretét, és ezért, ha kezdetben azt feltételeztem, hogy a regiszterelosztó a teljes jitter idő 5-10 százalékát dolgozza ki, akkor a valóságban az lett. 50 százalék.

Az idő előrehaladtával a fordító tisztább és hatékonyabb lett, több esetben nem generált szörnyű kódokat, és a teljesítménye egyre inkább hasonlított egy C fordítóhoz. Hacsak nem írsz olyan baromságot, amit még a C sem gyorsít. . Ha olyan kódot ír, mint a C, akkor több esetben olyan teljesítményt kap, mint a C. És minél tovább ment, annál gyakrabban kapott olyan kódot, amely aszimptotikusan egybeesett a C szinttel, a regiszterelosztó kezdett valami teljesnek látszani... függetlenül attól, hogy a kód gyorsan vagy lassan fut. Tovább dolgoztam az allokátoron, hogy jobb legyen a kiválasztás. Egyre lassabb lett, de egyre jobb teljesítményt nyújtott olyan esetekben, amikor más nem tudott megbirkózni. Beleugrom egy regiszterelosztóba, eltemethetek egy hónapnyi munkát, és hirtelen az egész kód 5%-kal gyorsabban futni kezd. Ez időről időre megtörtént, és a regiszterelosztó valamiféle műalkotássá vált - mindenki szerette vagy utálta, és az akadémiáról kérdéseket tettek fel a „miért van minden így”, miért nem. vonal pásztázás, és mi a különbség. A válasz továbbra is ugyanaz: a gráfszínezésen alapuló allokátor, valamint a pufferkóddal végzett nagyon gondos munka egyenlő a győzelem fegyverével, a legjobb kombinációval, amelyet senki sem tud legyőzni. És ez egy meglehetősen nem nyilvánvaló dolog. Minden más, amit a fordító csinál ott, eléggé áttanulmányozott dolog, bár ezeket is a művészet szintjére hozták. Mindig olyan dolgokat csináltam, amelyeknek a fordítóból műalkotást kellett volna csinálniuk. De ebben semmi sem volt rendkívüli – kivéve a regiszterelosztót. A trükk az, hogy légy óvatos levágni terhelés alatt, és ha ez megtörténik (ha érdekel, részletesebben el tudom magyarázni), ez azt jelenti, hogy agresszívebben léphet be, anélkül, hogy fennállna annak a veszélye, hogy elesik az előadási ütemtervben. Abban az időben egy csomó teljes méretű fordítóprogram volt, csecsebecsékkel és síppal lógatva, amelyekben regiszterelosztók voltak, de ezt senki más nem tudta megtenni.

A probléma az, hogy ha olyan metódusokat adunk hozzá, amelyek beilleszthetőek, növelik és növelik a beillesztési területet, akkor a használt értékek halmaza azonnal meghaladja a regiszterek számát, és le kell vágnia őket. A kritikus szint általában akkor jön el, amikor az allokátor feladja, és egy jó jelölt a kiömlésre megér egy másikat, akkor eladsz néhány általában vad dolgot. Az inlining értéke itt az, hogy elveszíti a rezsi egy részét, a hívás és a mentés rezsijét, láthatja az értékeket belül, és tovább optimalizálhatja azokat. Az inlining költsége az, hogy nagyszámú élő érték keletkezik, és ha a regiszterelosztó a szükségesnél többet ég le, azonnal veszít. Ezért a legtöbb allokátornak van egy problémája: amikor a betét átlép egy bizonyos határvonalat, a világon mindent elkezd lefaragni, és a termelékenységet le lehet öblíteni a WC-n. Azok, akik megvalósítják a fordítót, hozzátesznek néhány heurisztikát: például le kell állítani a beágyazást, kezdve valami kellően nagy mérettel, mivel az allokációk mindent tönkretesznek. Így alakul ki egy törés a teljesítmény grafikonon - inline, inline, a teljesítmény lassan nő -, majd bumm! – úgy esik le, mint egy gyors emelő, mert túl sokat béleltél. Így működött minden a Java megjelenése előtt. A Java sokkal több beágyazást igényel, ezért sokkal agresszívebbé kellett tennem az allokátoromat, hogy ne lefagyjon, hanem kiegyenlítsen, és ha túl sokat inline-el, akkor elkezd ömleni, de akkor mégis eljön a „no more spilling” pillanat. Ez egy érdekes megfigyelés, és csak a semmiből jutott eszembe, nem nyilvánvaló, de jól kifizetődött. Felvettem az agresszív beillesztést, és olyan helyekre vittem, ahol a Java és a C teljesítmény egymás mellett működik. Nagyon közel állnak egymáshoz – tudok olyan Java kódot írni, ami lényegesen gyorsabb, mint a C kód és hasonlók, de átlagosan a dolgok nagy képében nagyjából összehasonlíthatóak. Szerintem ennek az érdemnek része a regiszterelosztó, amely lehetővé teszi, hogy a lehető leghülyébb módon besoroljak. Csak beleírok mindent, amit látok. A kérdés itt az, hogy jól működik-e az allokátor, hogy az eredmény intelligensen működő kód-e. Ez nagy kihívás volt: mindezt megérteni és működőképessé tenni.

Egy kicsit a regiszterelosztásról és a többmagosról

Vladimir: Az olyan problémák, mint a regiszterkiosztás, valamiféle örök, végtelen témának tűnnek. Kíváncsi vagyok, volt-e valaha olyan ötlet, amely ígéretesnek tűnt, majd a gyakorlatban megbukott?

Szikla: Természetesen! A regiszter-allokáció egy olyan terület, ahol megpróbálja megtalálni a heurisztikát egy NP-teljes probléma megoldásához. És soha nem lehet tökéletes megoldást elérni, igaz? Ez egyszerűen lehetetlen. Nézd, Ahead of Time összeállítás – ez is rosszul működik. A beszélgetés itt néhány átlagos esetről szól. A tipikus teljesítményről, hogy elmész és mérhetsz valamit, ami szerinted jó tipikus teljesítmény – elvégre ezen dolgozol! A regisztrációk kiosztása a teljesítményről szól. Ha megvan az első prototípus, az működik, és lefesti, amit kell, kezdődik az előadói munka. Meg kell tanulni jól mérni. Miért fontos? Ha egyértelmű adatokkal rendelkezik, megtekintheti a különböző területeket, és láthatja: igen, itt segített, de itt minden elromlott! Jön néhány jó ötlet, új heurisztikát ad hozzá, és hirtelen minden átlagosan kicsit jobban kezd működni. Vagy nem indul el. Volt egy csomó olyan esetem, amikor az öt százalékos teljesítményért küzdöttünk, ami megkülönböztette a fejlődésünket a korábbi allokátortól. És minden alkalommal így néz ki: hol nyersz, hol veszítesz. Ha jó teljesítményelemző eszközökkel rendelkezik, megtalálhatja a vesztes ötleteket, és megértheti, miért nem sikerülnek. Esetleg érdemes mindent úgy hagyni, ahogy van, esetleg komolyabban hozzáállni a finomhangoláshoz, vagy kimenni valami mást javítani. Ez egy csomó dolog! Elkészítettem ezt a klassz hacket, de nekem is kell ez, meg ez, meg ez – és ezek teljes kombinációja némi javulást ad. A magányosok pedig elbukhatnak. Ez az NP-teljes problémákon végzett teljesítménymunka jellege.

Vladimir: Az embernek az az érzése, hogy az olyan dolgok, mint a festés az allokátorokban, már megoldott probléma. Nos, ez neked dőlt el, abból ítélve, amit mondasz, akkor még megéri...

Szikla: Ez nincs így megoldva. Neked kell „megoldottá” alakítanod. Vannak nehéz problémák, és ezeket meg kell oldani. Ha ez megtörtént, ideje dolgozni a termelékenységen. Ennek megfelelően kell megközelítenie ezt a munkát - benchmarkokat kell végeznie, mérőszámokat gyűjteni, elmagyarázni azokat a helyzeteket, amikor egy korábbi verzióra való visszatéréskor a régi hack újra működni kezdett (vagy fordítva, leállt). És ne add fel, amíg el nem érsz valamit. Ahogy már mondtam, ha vannak jó ötletek, amelyek nem működtek, de az ötletnyilvántartások kiosztása terén ez megközelítőleg végtelen. Olvashat például tudományos publikációkat. Bár most ez a terület sokkal lassabban kezdett mozogni, és tisztábbá vált, mint fiatalkorában. Viszont számtalan ember dolgozik ezen a területen, és minden ötletüket érdemes kipróbálni, mind a szárnyakban vár. És nem tudod megmondani, milyen jók, ha nem próbálod ki. Mennyire jól integrálódnak minden mással az Ön allokátorában, mert egy allokátor sok mindent megtesz, és egyes ötletek nem működnek az adott allokátorban, de egy másik allokátorban könnyen. Az allokátor nyerésének fő módja az, hogy a lassú dolgokat a fő útvonalon kívülre húzzuk, és a lassú utak határai mentén kettéválásra kényszerítjük. Tehát ha egy GC-t akarsz futtatni, válassz lassú utat, deoptimálsz, dobj kivételt, minden ilyesmi – tudod, hogy ezek a dolgok viszonylag ritkák. És tényleg ritkák, ellenőriztem. Ön extra munkát végez, és ez sok korlátozást megszüntet ezeken a lassú utakon, de ez nem igazán számít, mert lassúak és ritkán járnak. Például egy nulla mutató – soha nem történik meg, igaz? Különböző dolgokhoz több útra van szükség, de ezek nem zavarhatják a fő utat. 

Vladimir: Mi a véleményed a többmagosról, amikor több ezer mag van egyszerre? Ez hasznos dolog?

Szikla: A GPU sikere azt mutatja, hogy nagyon hasznos!

Vladimir: Eléggé specializáltak. Mi a helyzet az általános célú processzorokkal?

Szikla: Nos, ez volt Azul üzleti modellje. A válasz egy olyan korszakban jött vissza, amikor az emberek nagyon szerették a kiszámítható teljesítményt. Akkoriban nehéz volt párhuzamos kódot írni. A H2O kódolási modell nagymértékben skálázható, de nem általános célú modell. Talán egy kicsit általánosabb, mint a GPU használatakor. Egy ilyen dolog fejlesztésének bonyolultságáról vagy használatának bonyolultságáról beszélünk? Azul például egy érdekes leckét adott nekem, egy meglehetősen nem nyilvánvalót: a kis gyorsítótárak normálisak. 

A legnagyobb kihívás az életben

Vladimir: Mi a helyzet a nem technikai kihívásokkal?

Szikla: A legnagyobb kihívás az volt, hogy nem... kedvesnek és kedvesnek lenni az emberekkel. És ennek következtében folyamatosan rendkívül konfliktusos helyzetekbe kerültem. Azok, ahol tudtam, hogy a dolgok rosszul mennek, de nem tudtam, hogyan lépjek tovább ezekkel a problémákkal, és nem tudtam kezelni őket. Sok hosszú távú, évtizedekig tartó probléma merült fel így. Az a tény, hogy a Java C1 és C2 fordítókkal rendelkezik, ennek egyenes következménye. Az is egyenes következménye, hogy a Java nyelven tíz évig egymás után nem volt többszintű fordítás. Nyilvánvaló, hogy szükségünk volt egy ilyen rendszerre, de nem nyilvánvaló, hogy miért nem létezett. Problémám volt egy mérnökkel... vagy egy mérnökcsoporttal. Egyszer régen, amikor elkezdtem dolgozni a Sunnál, én... Oké, nem csak akkor, általában mindig mindenről megvan a saját véleményem. És azt hittem, hogy igaz, hogy ezt az igazságodat egyszerűen elmondhatod. Főleg, hogy az idő nagy részében megdöbbentően igazam volt. És ha nem tetszik ez a megközelítés... főleg, ha nyilvánvalóan tévedsz és hülyeségeket csinálsz... Általában kevesen tudnák elviselni ezt a kommunikációs formát. Bár néhányan megtehetnék, mint én. Egész életemet meritokratikus elvekre építettem. Ha rosszat mutatsz, azonnal megfordulok, és azt mondom: hülyeséget mondtál. Egyúttal természetesen elnézést kérek, meg minden, megjegyzem az érdemeket, ha vannak, és megteszem az egyéb helyes intézkedéseket. A teljes idő megdöbbentően nagy százalékában viszont megdöbbentően igazam van. És ez nem működik túl jól az emberekkel való kapcsolatokban. Nem próbálok kedves lenni, de nyersen teszem fel a kérdést. "Ez soha nem fog működni, mert egy, kettő és három." És azt mondták: "Ó!" Voltak más következmények is, amelyeket valószínűleg jobb figyelmen kívül hagyni: például azok, amelyek a feleségemtől való váláshoz, majd tíz év depresszióhoz vezettek.

A kihívás az emberekkel való küzdelem, azzal, hogy felfogják, mit tehetsz vagy nem, mi a fontos és mi nem. Sok kihívást jelentett a kódolási stílus. Még mindig sok kódot írok, és akkoriban még lassítanom is kellett, mert túl sok párhuzamos feladatot és rosszul csináltam, ahelyett, hogy egyre koncentráltam volna. Visszatekintve a Java JIT parancshoz írtam a kód felét, a C2 parancsot. A következő leggyorsabb kódoló fele lassabban írt, a következő fele lassabban, és ez exponenciális csökkenés volt. A hetedik ember ebben a sorban nagyon-nagyon lassú volt – ez mindig megtörténik! Sok kódot érintettem. Megnéztem, ki mit írt, kivétel nélkül a kódjukat bámultam, mindegyiket átnéztem, és továbbra is többet írtam magam, mint bármelyikük. Ez a megközelítés nem működik túl jól az emberekkel. Néhány embernek ez nem tetszik. És amikor nem tudják kezelni, mindenféle panasz kezdődik. Például egyszer azt mondták nekem, hogy hagyjam abba a kódolást, mert túl sok kódot írok, és ez veszélyezteti a csapatot, és ez az egész viccnek tűnt nekem: haver, ha a csapat többi tagja eltűnik és én tovább írok kódot, te Csak fél csapatot veszítek. Másrészt, ha folyamatosan írok kódot, és elveszíted a csapat felét, az nagyon rossz irányításnak hangzik. Soha nem gondoltam rá igazán, soha nem beszéltem róla, de valahol még mindig ott volt a fejemben. A gondolatom kavargott a fejemben: „Mind viccelsz velem?” Szóval a legnagyobb probléma én és az emberekkel való kapcsolataim voltak. Most már sokkal jobban megértem magam, sokáig programozók csapatvezetője voltam, most pedig egyenesen azt mondom az embereknek: tudod, az vagyok, aki vagyok, és neked kell foglalkoznod velem – nem baj, ha kiállok. itt? És amikor elkezdtek foglalkozni vele, minden működött. Valójában nem vagyok se rossz, se jó, nincsenek rossz szándékaim vagy önző törekvéseim, ez csak a lényegem, és valahogy együtt kell élnem vele.

Andrew: Nemrég kezdett mindenki az introvertáltak önismeretéről és általában a soft skillekről beszélni. Mit lehet erre mondani?

Szikla: Igen, ez volt az a belátás és a lecke, amit a feleségemtől való válásomból tanultam. A válásból tanultam, hogy megértettem magam. Így kezdtem megérteni másokat. Ismerje meg, hogyan működik ez az interakció. Ez egymás után vezetett felfedezésekhez. Megvolt a tudat, hogy ki vagyok és mit képviselek. Mit csinálok: vagy a feladattal vagyok elfoglalva, vagy kerülöm a konfliktust, vagy valami mást – és az önismeretnek ez a szintje nagyon segít az irányításban. Ezek után minden sokkal könnyebben megy. Egy dolog, amit nem csak magamban, hanem más programozókban is felfedeztem, az az, hogy képtelenség szavakba önteni a gondolatait, amikor érzelmi stresszes állapotban vagy. Például ott ülsz és kódolsz, áramlási állapotban, majd odarohannak hozzád, és hisztérikusan üvöltözni kezdenek, hogy valami elromlott, és most szélsőséges intézkedéseket fognak hozni ellened. És egy szót sem szólhatsz, mert érzelmi stressz állapotban vagy. Az elsajátított tudás lehetővé teszi, hogy felkészülj erre a pillanatra, túléld azt és továbblépj egy visszavonulási tervre, ami után már tehetsz is valamit. Tehát igen, amikor elkezdi felismerni, hogyan működik mindez, az egy hatalmas életet megváltoztató esemény. 
Jómagam nem találtam a megfelelő szavakat, de emlékeztem a cselekvések sorozatára. A lényeg az, hogy ez a reakció éppúgy fizikai, mint verbális, és szükséged van térre. Ilyen tér, a zen értelmében. Pontosan ezt kell megmagyarázni, majd azonnal félrelépni – pusztán fizikailag lépni. Ha verbálisan csendben maradok, akkor érzelmileg fel tudom dolgozni a helyzetet. Ahogy az adrenalin eléri az agyat, harci vagy repülési módba kapcsol, már nem mondhatsz semmit, nem - most egy idióta vagy, egy ostoros mérnök, aki nem képes tisztességes reakcióra, vagy akár megállítani a támadást, és a támadó szabadon van. újra és újra támadni. Először újra önmagaddá kell válnod, vissza kell szerezned az irányítást, ki kell lépned a „harcolj vagy menekülj” módból.

Ehhez pedig verbális térre van szükségünk. Csak szabad hely. Ha egyáltalán mond valamit, akkor pontosan ezt mondhatja, majd menjen, és keressen igazán „teret” magának: menjen sétálni a parkba, zárja be magát a zuhany alá - nem számít. A legfontosabb dolog az, hogy átmenetileg kiszakadjon ebből a helyzetből. Amint legalább néhány másodpercre kikapcsol, visszatér az irányítás, elkezd józanul gondolkodni. "Rendben, nem vagyok idióta, nem csinálok hülyeségeket, elég hasznos ember vagyok." Ha sikerült meggyőznie magát, ideje továbblépni a következő szakaszra: megérteni, mi történt. Megtámadtak, a támadás onnan jött, ahonnan nem számítottál rá, becstelen, aljas les volt. Ez rossz. A következő lépés annak megértése, hogy miért volt erre szüksége a támadónak. Tényleg, miért? Talán azért, mert ő maga is dühös? Miért haragszik? Például azért, mert elcseszte magát, és nem tud felelősséget vállalni? Így kell körültekintően kezelni az egész helyzetet. De ehhez mozgástér, verbális tér kell. A legelső lépés a verbális kapcsolat megszakítása. Kerülje a szavakkal folytatott vitát. Törölje, menjen el a lehető leggyorsabban. Ha telefonbeszélgetésről van szó, egyszerűen tedd le – ez egy olyan készség, amelyet a volt feleségemmel való kommunikáció során tanultam meg. Ha a beszélgetés nem vezet jóra, csak mondjon „viszlát”, és tegye le a telefont. A telefon másik oldaláról: "bla bla bla", Ön azt válaszolja: "igen, viszlát!" és tedd le. Csak fejezd be a beszélgetést. Öt perccel később, amikor visszatér benned az értelmes gondolkodás képessége, kicsit lehűlsz, lehetségessé válik, hogy mindenre gondolj, mi történt és mi fog ezután történni. És kezdjen el átgondolt választ megfogalmazni, ahelyett, hogy csak érzelmekből reagálna. Számomra az önismeretben az áttörést éppen az jelentette, hogy érzelmi stressz esetén nem tudok beszélni. Kilépni ebből az állapotból, gondolkodni és megtervezni, hogyan reagáljunk és kompenzáljuk a problémákat – ezek a helyes lépések abban az esetben, ha nem tud beszélni. A legegyszerűbb módja az, ha elmenekülünk abból a helyzetből, amelyben az érzelmi stressz megnyilvánul, és egyszerűen abbahagyja a stresszben való részvételt. Utána képessé válsz gondolkodni, amikor tudsz gondolkodni, akkor beszélni, és így tovább.

Mellesleg, a bíróságon az ellenérdekű ügyvéd megpróbálja ezt megtenni Önnel - most már világos, hogy miért. Mert képes olyan állapotba elnyomni, hogy például a nevedet sem tudod kiejteni. Valójában nem fogsz tudni beszélni. Ha ez megtörténik Önnel, és tudja, hogy olyan helyen találja magát, ahol szócsaták dúlnak, olyan helyen, mint a bíróság, akkor jöhet az ügyvédje. Az ügyvéd kiáll melletted és leállítja a verbális támadást, és ezt teljesen legális módon teszi, és az elveszett zen tér visszatér hozzád. Például párszor fel kellett hívnom a családomat, a bíró elég barátságos volt ezzel kapcsolatban, de a szemben álló ügyvéd sikoltozott és kiabált velem, szóhoz sem tudtam jutni. Ezekben az esetekben a közvetítő használata működik a legjobban számomra. A közvetítő leállítja ezt a folyamatos folyamban rád zúduló nyomást, megtalálod a szükséges zen teret, és vele együtt visszatér a beszédkészség. Ez egy egész tudásterület, amelyben rengeteget lehet tanulni, sok mindent felfedezni magunkban, és mindez magas szintű stratégiai döntésekké alakul, amelyek különbözőek az emberek számára. Vannak, akiknél nem jelentkeznek a fent leírt problémák; általában a professzionális értékesítőknek nincs ilyen problémájuk. Mindazoknak az embereknek, akik szavakkal keresik a kenyerüket - híres énekesek, költők, vallási vezetők és politikusok, mindig van mondanivalójuk. Nekik nincsenek ilyen problémáik, de nekem igen.

Andrew: Ez... váratlan volt. Remek, már sokat beszélgettünk, és ideje befejezni ezt az interjút. A konferencián biztosan találkozunk, és folytatni tudjuk ezt a párbeszédet. Találkozunk a Hydrában!

Folytathatja a beszélgetést Cliffel a Hydra 2019 konferencián, amelyet 11. július 12-2019-én rendeznek meg Szentpéterváron. Jön majd jelentéssel „Az Azul hardveres tranzakciós memória élménye”. Jegyek vásárolhatók a hivatalos weboldalon.

Forrás: will.com

Hozzászólás