Java-da JIT kompilyatsiyasining otasi Cliff Click bilan ajoyib intervyu

Java-da JIT kompilyatsiyasining otasi Cliff Click bilan ajoyib intervyuCliff Click — Cratus kompaniyasining texnik direktori (jarayonlarni takomillashtirish uchun IoT sensorlari), bir nechta startaplarning asoschisi va hammuassisi (jumladan, Rocket Realtime School, Neurensic va H2O.ai) bir nechta muvaffaqiyatli chiqishlari bilan. Cliff o'zining birinchi kompilyatorini 15 yoshida yozgan (TRS Z-80 uchun Paskal)! U Java-dagi C2 (The Sea of ​​Nodes IR) ishi bilan mashhur. Ushbu kompilyator jahonga JIT yuqori sifatli kod ishlab chiqarishi mumkinligini ko'rsatdi, bu Java tilining asosiy zamonaviy dasturiy platformalardan biri sifatida paydo bo'lishining omillaridan biri bo'ldi. Keyin Cliff Azul Systems-ga 864 millisekundda 500 gigabaytlik yig'ma GC pauzalarini qo'llab-quvvatlovchi sof Java dasturiy ta'minotiga ega 10 yadroli meynfreym yaratishda yordam berdi. Umuman olganda, Kliff JVM ning barcha jihatlari ustida ishlashga muvaffaq bo'ldi.

 
Bu habrapost Cliff bilan ajoyib intervyu. Biz quyidagi mavzularda suhbatlashamiz:

  • Past darajadagi optimallashtirishga o'tish
  • Katta refaktoringni qanday qilish kerak
  • Narx modeli
  • Past darajadagi optimallashtirish bo'yicha trening
  • Samaradorlikni oshirishning amaliy misollari
  • Nima uchun o'z dasturlash tilingizni yaratasiz
  • Ishlash muhandisi martaba
  • Texnik qiyinchiliklar
  • Registrni ajratish va ko'p yadroli haqida bir oz
  • Hayotdagi eng katta qiyinchilik

Suhbat quyidagi tomonidan o'tkaziladi:

  • Andrey Satarin Amazon veb-xizmatlaridan. O'z karerasida u butunlay boshqa loyihalarda ishlashga muvaffaq bo'ldi: u Yandex-da tarqatilgan NewSQL ma'lumotlar bazasini, Kasperskiy laboratoriyasida bulutlarni aniqlash tizimini, Mail.ru-da multiplayer o'yinini va Deutsche Bank-da valyuta narxlarini hisoblash xizmatini sinab ko'rdi. Keng miqyosli backend va taqsimlangan tizimlarni sinab ko'rishga qiziqadi.
  • Vladimir Sitnikov Netcracker'dan. NetCracker OS, tarmoq va tarmoq uskunalarini boshqarish jarayonlarini avtomatlashtirish uchun aloqa operatorlari tomonidan qo'llaniladigan dasturiy ta'minotning ishlashi va kengaytirilishi bo'yicha o'n yillik ish. Java va Oracle ma'lumotlar bazasi ishlashi bilan bog'liq muammolarga qiziqadi. Rasmiy PostgreSQL JDBC drayverida o'ndan ortiq ish faoliyatini yaxshilash muallifi.

Past darajadagi optimallashtirishga o'tish

Andrew: Siz JIT kompilyatsiyasi, Java va umuman ishlash bo'yicha dunyoda katta nomsiz, to'g'rimi? 

Cliff: Xuddi shunday!

Andrew: Keling, ishlashga oid umumiy savollardan boshlaylik. CPU darajasida ishlash kabi yuqori darajali va past darajadagi optimallashtirish o'rtasidagi tanlov haqida nima deb o'ylaysiz?

Cliff: Ha, bu erda hamma narsa oddiy. Eng tezkor kod hech qachon ishlamaydigan koddir. Shuning uchun siz doimo yuqori darajadan boshlashingiz, algoritmlar ustida ishlashingiz kerak. Agar yetarlicha katta konstantalar aralashmasa, yaxshiroq O belgisi yomonroq O belgisini uradi. Past darajadagi narsalar oxirgi o'rinda turadi. Odatda, agar siz stekning qolgan qismini etarlicha optimallashtirgan bo'lsangiz va hali ham qiziqarli narsalar qolsa, bu past darajadir. Lekin qanday qilib yuqori darajadan boshlash kerak? Etarli darajada yuqori ish qilinganligini qayerdan bilasiz? Xo'sh... yo'q. Tayyor retseptlar yo'q. Muammoni tushunishingiz kerak, nima qilishni hal qilishingiz kerak (kelajakda keraksiz qadamlar qo'ymaslik uchun) va keyin siz foydali narsalarni ayta oladigan profilerni ochishingiz mumkin. Bir nuqtada, siz o'zingiz keraksiz narsalardan xalos bo'lganingizni tushunasiz va past darajadagi nozik sozlash vaqti keldi. Bu, albatta, san'atning o'ziga xos turi. Ko'p odamlar keraksiz ishlar bilan shug'ullanadi, lekin shunchalik tez harakat qiladiki, ular hosildorlik haqida qayg'urishga vaqtlari yo'q. Ammo bu savol to'g'ridan-to'g'ri paydo bo'lguncha. Odatda 99% hollarda, men nima qilayotganimni hech kim qiziqtirmaydi, toki muhim narsa hech kimni qiziqtirmaydigan muhim yo'lda paydo bo'lguncha. Va bu erda hamma sizni "nima uchun u boshidanoq mukammal ishlamadi" deb bezovta qila boshlaydi. Umuman olganda, har doim ishlashni yaxshilash uchun biror narsa bor. Ammo 99% hollarda sizda hech qanday sabab yo'q! Siz shunchaki biror narsani amalga oshirishga harakat qilyapsiz va bu jarayonda nima muhimligini tushunasiz. Siz hech qachon bu asar mukammal bo'lishi kerakligini oldindan bila olmaysiz, shuning uchun aslida siz hamma narsada mukammal bo'lishingiz kerak. Ammo bu mumkin emas va siz buni qilmaysiz. Har doim tuzatish uchun juda ko'p narsa bor - va bu mutlaqo normaldir.

Katta refaktoringni qanday qilish kerak

Andrew: Spektakl ustida qanday ishlaysiz? Bu o'zaro bog'liq muammo. Misol uchun, ko'plab mavjud funktsiyalarning kesishishidan kelib chiqadigan muammolar ustida ishlashingiz kerak bo'lganmi?

Cliff: Men undan qochishga harakat qilaman. Agar men ishlash muammosi bo'lishini bilsam, kodlashni boshlashdan oldin, ayniqsa ma'lumotlar tuzilmalari bilan bu haqda o'ylayman. Ammo ko'pincha bularning barchasini keyinroq bilib olasiz. Va keyin siz haddan tashqari choralarga borishingiz va men "qayta yozish va zabt etish" deb ataydigan narsani qilishingiz kerak: siz etarlicha katta bo'lakni olishingiz kerak. Ba'zi kodlar ishlash muammolari yoki boshqa sabablarga ko'ra qayta yozilishi kerak bo'ladi. Kodni qayta yozishning sababi nima bo'lishidan qat'iy nazar, kichikroq bo'lakdan ko'ra kattaroq bo'lakni qayta yozish deyarli har doim yaxshiroqdir. Bu vaqtda hamma qo'rquvdan titra boshlaydi: "Ey Xudoyim, siz juda ko'p kodga tegolmaysiz!" Lekin, aslida, bu yondashuv deyarli har doim ancha yaxshi ishlaydi. Siz darhol katta muammoni hal qilishingiz, uning atrofida katta doira chizishingiz va aytishingiz kerak: men doira ichidagi hamma narsani qayta yozaman. Chegarasi o'zgartirilishi kerak bo'lgan uning ichidagi tarkibdan ancha kichikroq. Va agar chegaralarning bunday belgilanishi sizni ichkaridagi ishni mukammal bajarishga imkon bersa, qo'llaringiz bo'sh, xohlaganingizni qiling. Muammoni tushunganingizdan so'ng, qayta yozish jarayoni ancha osonlashadi, shuning uchun katta luqma oling!
Shu bilan birga, siz katta hajmdagi qayta yozishni amalga oshirganingizda va ishlash muammo bo'lishini tushunsangiz, darhol bu haqda tashvishlanishni boshlashingiz mumkin. Bu, odatda, "ma'lumotlarni nusxa ko'chirmang, ma'lumotlarni iloji boricha sodda tarzda boshqaring, uni kichikroq qiling" kabi oddiy narsalarga aylanadi. Katta qayta yozishlarda ishlashni yaxshilashning standart usullari mavjud. Va ular deyarli har doim ma'lumotlar atrofida aylanadi.

Narx modeli

Andrew: Podkastlardan birida siz mahsuldorlik kontekstidagi xarajat modellari haqida gapirdingiz. Bu bilan nimani nazarda tutganingizni tushuntirib bera olasizmi?

Cliff: Albatta. Men protsessor ishlashi juda muhim bo'lgan davrda tug'ilganman. Va bu davr yana qaytadi - taqdir istehzosiz emas. Men sakkiz bitli mashinalar davrida yashay boshladim; mening birinchi kompyuterim 256 bayt bilan ishlagan. Aynan baytlar. Hamma narsa juda kichik edi. Ko'rsatmalarni hisoblash kerak edi va biz dasturlash tillari to'plamini yuqoriga ko'tarishni boshlaganimizdan so'ng, tillar tobora ko'proq o'zlashtirildi. Assembler bor edi, keyin Basic, keyin C va C registrlarni ajratish va ko'rsatmalarni tanlash kabi ko'plab tafsilotlarga g'amxo'rlik qildi. Ammo u erda hamma narsa aniq edi va agar men o'zgaruvchining misoliga ko'rsatgich qilsam, men yuk olaman va bu ko'rsatmaning narxi ma'lum. Uskuna ma'lum miqdordagi mashina tsikllarini ishlab chiqaradi, shuning uchun har xil narsalarni bajarish tezligini siz ishga tushirmoqchi bo'lgan barcha ko'rsatmalarni qo'shish orqali hisoblash mumkin. Har bir solishtirish/sinov/filial/qo'ng'iroq/yuklash/do'konni qo'shib aytish mumkin: bu siz uchun ijro vaqti. Ishlashni yaxshilash ustida ishlayotganingizda, siz qaysi raqamlar kichik issiq davrlarga mos kelishiga e'tibor berasiz. 
Ammo Java, Python va shunga o'xshash narsalarga o'tish bilanoq, siz past darajadagi apparatdan juda tez uzoqlashasiz. Java-da qabul qiluvchiga qo'ng'iroq qilish qancha turadi? HotSpot-da JIT to'g'ri bo'lsa chizilgan, u yuklanadi, lekin agar u buni qilmagan bo'lsa, bu funktsiya chaqiruvi bo'ladi. Qo'ng'iroq tezkor rejimda bo'lgani uchun u ushbu tsikldagi barcha boshqa optimallashtirishlarni bekor qiladi. Shuning uchun haqiqiy xarajat ancha yuqori bo'ladi. Va siz darhol kodning bir qismini ko'rib chiqish qobiliyatini yo'qotasiz va biz uni protsessorning soat tezligi, xotira va keshdan foydalanish nuqtai nazaridan bajarishimiz kerakligini tushunasiz. Bularning barchasi, agar siz haqiqatan ham spektaklga kirsangiz, qiziqarli bo'ladi.
Endi biz protsessor tezligi o'n yil davomida deyarli oshmagan vaziyatga tushib qoldik. Eski kunlar qaytib keldi! Siz endi yaxshi bitta ipli ishlashga ishona olmaysiz. Ammo, agar siz to'satdan parallel hisoblash bilan shug'ullansangiz, bu juda qiyin, hamma sizga Jeyms Bond kabi qaraydi. Bu erda o'n barobar tezlashuv odatda kimdir biror narsani buzgan joylarda sodir bo'ladi. Birgalikda ishlash ko'p mehnat talab qiladi. Ushbu XNUMXx tezlikni olish uchun siz xarajat modelini tushunishingiz kerak. Bu nima va qancha turadi? Va buning uchun siz tilning asosiy uskunaga qanday mos kelishini tushunishingiz kerak.
Martin Tompson o'z blogi uchun ajoyib so'z tanladi Mexanik simpatiya! Uskuna nima qilishini, uni qanday aniq bajarishini va nima uchun birinchi navbatda nima qilishini tushunishingiz kerak. Bundan foydalanib, ko'rsatmalarni hisoblash va ijro vaqti qayerga ketayotganini aniqlash juda oson. Agar sizda tegishli tayyorgarlik bo'lmasa, siz qorong'i xonada qora mushukni qidiryapsiz. Men har doim ishlashni optimallashtiradigan odamlarni ko'raman, ular nima qilayotganini bilmaydilar. Ular juda ko'p azob chekishadi va katta muvaffaqiyatga erisha olmaydilar. Va men bir xil kod qismini olganimda, bir nechta kichik buzg'unchiliklarni kiritib, besh yoki o'n baravar tezlashtirishga erishganimda, ular shunday bo'ladi: yaxshi, bu adolatdan emas, biz sizdan yaxshiroq ekanligingizni allaqachon bilardik. Ajoyib. Men nima haqida gapiryapman ... xarajat modeli siz qanday kod yozishingiz va katta rasmda o'rtacha qanchalik tez ishlashi haqida.

Andrew: Va qanday qilib bunday hajmni boshingizda ushlab turishingiz mumkin? Bunga ko'proq tajriba bilan erishiladimi yoki? Bunday tajriba qayerdan keladi?

Cliff: Xo'sh, men o'z tajribamni eng oson yo'l bilan olmadim. Men Assambleyada har bir ko'rsatmani tushunishingiz mumkin bo'lgan kunlarda dasturlashtirganman. Bu ahmoqona tuyuladi, lekin o'shandan beri Z80 ko'rsatmalar to'plami doimo mening boshimda, xotiramda saqlanib qolgan. Men gaplashgandan keyin bir daqiqada odamlarning ismlarini eslay olmayman, lekin 40 yil oldin yozilgan kodni eslayman. Bu kulgili, bu sindromga o'xshaydi "ahmoq olim".

Past darajadagi optimallashtirish bo'yicha trening

Andrew: Kirishning osonroq yo'li bormi?

Cliff: Ha va yo'q. Barchamiz foydalanadigan apparat vaqt o'tishi bilan unchalik o'zgarmadi. Arm smartfonlaridan tashqari hamma x86 dan foydalanadi. Agar siz qandaydir qattiq o'rnatish bilan shug'ullanmasangiz, xuddi shu narsani qilyapsiz. Mayli, keyingisi. Ko'rsatmalar ham asrlar davomida o'zgarmadi. Assambleyaga borib biror narsa yozishingiz kerak. Ko'p emas, lekin tushunishni boshlash uchun etarli. Siz tabassum qilasiz, lekin men butunlay jiddiy gapiryapman. Til va apparat o'rtasidagi yozishmalarni tushunishingiz kerak. Shundan so'ng siz borib, bir oz yozishingiz va kichik o'yinchoq tili uchun kichik o'yinchoq kompilyatorini qilishingiz kerak. O'yinchoqqa o'xshash, uni oqilona vaqt ichida qilish kerakligini anglatadi. Bu juda oddiy bo'lishi mumkin, lekin u ko'rsatmalar yaratishi kerak. Ko'rsatma yaratish harakati har bir kishi yozadigan yuqori darajadagi kod va apparatda ishlaydigan mashina kodi o'rtasidagi ko'prik uchun xarajat modelini tushunishga yordam beradi. Bu yozishmalar kompilyator yozilayotgan paytda miyaga yoqib yuboriladi. Hatto eng oddiy kompilyator ham. Shundan so'ng, siz Java-ga qarashni boshlashingiz mumkin va uning semantik jarlik ancha chuqurroq ekanligi va uning ustida ko'prik qurish ancha qiyinroq. Java-da, bizning ko'prik yaxshi yoki yomon bo'lganligini, uning parchalanishiga nima sabab bo'lishini va nima bo'lmasligini tushunish ancha qiyin. Ammo sizga kodni ko'rib chiqadigan va tushunadigan boshlang'ich nuqta kerak: "ha, bu oluvchi har safar kiritilishi kerak." Va keyin ma'lum bo'lishicha, ba'zida bu sodir bo'ladi, faqat usul juda katta bo'lganda va JIT hamma narsani kiritishni boshlaydi. Bunday joylarning ishlashini darhol taxmin qilish mumkin. Odatda oluvchilar yaxshi ishlaydi, lekin keyin siz katta issiq tsikllarga qaraysiz va u erda nima qilayotganini bilmaydigan ba'zi funktsional chaqiruvlar borligini tushunasiz. Bu getterlarning keng qo'llanilishi bilan bog'liq muammo, ular ichkariga kiritilmaganligining sababi, ular getter yoki yo'qligi aniq emas. Agar sizda juda kichik kod bazasi bo'lsa, uni shunchaki eslab, keyin aytishingiz mumkin: bu oluvchi va bu sozlovchi. Katta kod bazasida har bir funktsiya o'z tarixini yashaydi, bu umuman hech kimga ma'lum emas. Profilerning aytishicha, biz ba'zi bir tsiklda 24% vaqtni yo'qotdik va bu tsikl nima qilayotganini tushunish uchun biz ichidagi har bir funktsiyani ko'rib chiqishimiz kerak. Funktsiyani o'rganmasdan buni tushunish mumkin emas va bu tushunish jarayonini jiddiy ravishda sekinlashtiradi. Shuning uchun men oluvchi va sozlagichlardan foydalanmayman, men yangi darajaga yetdim!
Narx modelini qayerdan olish mumkin? To‘g‘risi, biror narsani o‘qishingiz mumkin, albatta... Lekin menimcha, eng yaxshi yo‘l harakat qilishdir. Kichik kompilyatorni yaratish xarajat modelini tushunish va uni o'z boshingizga moslashtirishning eng yaxshi usuli bo'ladi. Mikroto'lqinli pechni dasturlash uchun mos bo'lgan kichik kompilyator yangi boshlanuvchilar uchun vazifadir. Xo'sh, aytmoqchimanki, agar sizda dasturlash qobiliyatingiz bo'lsa, bu etarli bo'ladi. Bularning barchasi algebraik ifoda sifatida mavjud bo'lgan satrni tahlil qilish, u erdan to'g'ri tartibda matematik operatsiyalar uchun ko'rsatmalar olish, registrlardan to'g'ri qiymatlarni olish - bularning barchasi bir vaqtning o'zida amalga oshiriladi. Va buni qilayotganingizda, u sizning miyangizga muhrlanadi. Menimcha, kompilyator nima qilishini hamma biladi. Va bu xarajat modeli haqida tushuncha beradi.

Samaradorlikni oshirishning amaliy misollari

Andrew: Hosildorlik ustida ishlashda yana nimalarga e'tibor berish kerak?

Cliff: Ma'lumotlar tuzilmalari. Aytgancha, ha, men bu darslarni uzoq vaqtdan beri o'rgatmaganman ... Raketa maktabi. Bu qiziqarli edi, lekin bu juda ko'p kuch talab qildi va menda ham hayot bor! KELISHDIKMI. Shunday qilib, katta va qiziqarli darslardan birida "Sizning ishlashingiz qayerga ketadi" deb o'quvchilarga misol keltirdim: CSV faylidan ikki yarim gigabaytlik fintech ma'lumotlari o'qildi va keyin ular sotilgan mahsulotlar sonini hisoblashlari kerak edi. . Shomil bozorining muntazam ma'lumotlari. UDP paketlari 70-yillardan boshlab matn formatiga aylantirildi. Chikago savdo birjasi - sariyog ', makkajo'xori, soya fasulyesi kabi har xil narsalar. Ushbu mahsulotlarni, bitimlar sonini, mablag'lar va tovarlar harakatining o'rtacha hajmini va boshqalarni hisoblash kerak edi. Bu juda oddiy savdo matematikasi: mahsulot kodini toping (bu xesh-jadvalda 1-2 belgi), miqdorni oling, uni savdo to'plamlaridan biriga qo'shing, hajm qo'shing, qiymat qo'shing va boshqa bir nechta narsa. Juda oddiy matematika. O'yinchoqni amalga oshirish juda oddiy edi: hamma narsa faylda, men faylni o'qiyman va u orqali harakat qilaman, individual yozuvlarni Java satrlariga ajrataman, ulardagi kerakli narsalarni qidiraman va yuqorida tavsiflangan matematikaga muvofiq qo'shaman. Va u past tezlikda ishlaydi.

Ushbu yondashuv bilan nima sodir bo'layotgani aniq va parallel hisoblash yordam bermaydi, to'g'rimi? Ma'lum bo'lishicha, unumdorlikni besh baravar oshirishga faqat to'g'ri ma'lumotlar tuzilmalarini tanlash orqali erishish mumkin. Va bu hatto tajribali dasturchilarni ham hayratda qoldiradi! Mening alohida ishimda, hiyla-nayrang shundaki, siz xotirani issiq tsiklda taqsimlamasligingiz kerak. Xo'sh, bu butun haqiqat emas, lekin umuman olganda - X etarlicha katta bo'lsa, "Xda bir marta" ni ta'kidlamaslik kerak. X ikki yarim gigabayt bo'lsa, siz "har bir harfga bir marta", "har bir satrga bir marta" yoki "har bir maydonga bir marta", shunga o'xshash narsalarni ajratmasligingiz kerak. Bu erda vaqt sarflanadi. Bu hatto qanday ishlaydi? Men qo'ng'iroq qilayotganimni tasavvur qiling String.split() yoki BufferedReader.readLine(). Readline tarmoq orqali kelgan baytlar to‘plamidan har bir satr uchun bir martadan, yuzlab million satrlarning har biri uchun satr hosil qiladi. Men bu chiziqni olaman, uni tahlil qilaman va tashlayman. Nega men uni tashlab ketyapman - yaxshi, men uni qayta ishladim, hammasi. Shunday qilib, ushbu 2.7G dan o'qilgan har bir bayt uchun satrda ikkita belgi yoziladi, ya'ni allaqachon 5.4G va menga boshqa hech narsa kerak emas, shuning uchun ular tashlanadi. Agar siz xotira o'tkazish qobiliyatiga qarasangiz, biz protsessorda xotira va xotira avtobusi orqali o'tadigan 2.7G yuklaymiz, keyin esa xotirada yotgan chiziqqa ikki baravar ko'p yuboriladi va bularning barchasi har bir yangi chiziq yaratilganda eskiradi. Lekin men uni o'qishim kerak, apparat uni o'qiydi, hatto keyinroq hamma narsa eskirgan bo'lsa ham. Va men uni yozishim kerak, chunki men chiziq yaratdim va keshlar to'la - kesh 2.7G ni sig'dira olmaydi. Shunday qilib, men o'qigan har bir bayt uchun yana ikki bayt o'qiyman va yana ikkita bayt yozaman va oxirida ular 4: 1 nisbatga ega - bu nisbatda biz xotira o'tkazish qobiliyatini behuda sarflaymiz. Va keyin shunday bo'ladi, agar men qilsam String.split() - bu oxirgi marta emas, ichkarida yana 6-7 maydon bo'lishi mumkin. Shunday qilib, CSV ni o'qish va keyin satrlarni tahlil qilishning klassik kodi xotira o'tkazish qobiliyatini siz xohlagan narsaga nisbatan taxminan 14:1 ga sarflashga olib keladi. Agar siz ushbu tanlovlarni tashlab qo'ysangiz, tezlikni besh baravar oshirishingiz mumkin.

Va bu unchalik qiyin emas. Agar siz kodga to'g'ri burchakdan qarasangiz, muammoni tushunganingizdan so'ng, hamma narsa juda oddiy bo'ladi. Xotirani taqsimlashni butunlay to'xtatmasligingiz kerak: yagona muammo shundaki, siz biror narsani ajratasiz va u darhol o'ladi va yo'lda u muhim manbani yoqib yuboradi, bu holda bu xotira o'tkazish qobiliyati. Va bularning barchasi hosildorlikning pasayishiga olib keladi. X86-da siz odatda protsessor davrlarini faol ravishda yoqishingiz kerak, ammo bu erda siz barcha xotirani ancha oldin yoqib yubordingiz. Yechim oqindi miqdorini kamaytirishdir. 
Muammoning boshqa tomoni shundaki, agar siz xotira chizig'i tugashi bilanoq profilerni ishga tushirsangiz, u sodir bo'lganda, siz odatda keshning qaytib kelishini kutasiz, chunki u siz ishlab chiqargan axlatga to'la, barcha qatorlar. Shuning uchun, har bir yuk yoki do'kon ishi sekinlashadi, chunki ular kesh o'tkazib yuborilishiga olib keladi - butun kesh sekinlashdi va axlat uni tark etishini kutmoqda. Shuning uchun, profiler butun tsikl bo'ylab tarqalgan iliq tasodifiy shovqinni ko'rsatadi - kodda alohida issiq ko'rsatma yoki joy bo'lmaydi. Faqat shovqin. Va agar siz GC sikllariga qarasangiz, ularning barchasi Yosh avlod va juda tez - maksimal mikrosekundlar yoki millisekundlar. Axir, bu xotiraning barchasi bir zumda o'ladi. Siz milliardlab gigabaytlarni ajratasiz va u ularni kesib, kesib tashlaydi va yana kesib tashlaydi. Bularning barchasi juda tez sodir bo'ladi. Ma'lum bo'lishicha, arzon GC tsikllari, butun tsikl bo'ylab iliq shovqin bor, lekin biz 5x tezlashtirishni xohlaymiz. Ayni paytda sizning boshingizda nimadir yopilishi va: "Nega bu?!" Klassik nosozliklarni tuzatuvchida xotira chizig‘ining to‘lib ketishi ko‘rsatilmaydi; siz apparat unumdorligi hisoblagichini tuzatuvchini ishga tushirishingiz va uni o‘zingiz va bevosita ko‘rishingiz kerak. Ammo bu uchta alomatdan bevosita shubha qilish mumkin emas. Uchinchi alomat - siz ta'kidlagan narsangizga qaraganingizda, profilerdan so'rang va u javob beradi: "Siz bir milliard qator yaratdingiz, lekin GC bepul ishladi." Bu sodir bo'lishi bilan siz juda ko'p narsalarni yaratganingizni va butun xotira chizig'ini yoqib yuborganingizni tushunasiz. Buni aniqlashning bir yo'li bor, lekin bu aniq emas. 

Muammo ma'lumotlar tuzilmasida: sodir bo'layotgan hamma narsaning asosi bo'lgan yalang'och tuzilma, u juda katta, u diskda 2.7G, shuning uchun bu narsaning nusxasini yaratish juda istalmagan - uni darhol tarmoq bayt buferidan yuklamoqchisiz. registrlarga besh marta oldinga va orqaga o'qish-yozmaslik uchun. Afsuski, Java sukut bo'yicha JDK ning bir qismi sifatida sizga bunday kutubxonani bermaydi. Lekin bu ahamiyatsiz, to'g'rimi? Asosan, bu 5-10 qator kodlar bo'lib, ular o'zingizning buferlangan string yuklagichingizni amalga oshirish uchun ishlatiladi, bu esa string sinfining xatti-harakatlarini takrorlaydi va shu bilan birga asosiy bayt buferi atrofida o'raladi. Natijada, siz xuddi satrlar bilan ishlayotgandek ishlayapsiz, lekin aslida buferga ko'rsatgichlar harakatlanyapti va xom baytlar hech qayerga ko'chirilmaydi va shuning uchun bir xil buferlar qayta-qayta foydalaniladi va Operatsion tizim o'zi uchun mo'ljallangan narsalarni o'z zimmasiga olishdan mamnun bo'ladi, masalan, bu bayt buferlarini yashirin ikki marta buferlash va siz endi keraksiz ma'lumotlarning cheksiz oqimidan o'tmaysiz. Aytgancha, GC bilan ishlashda, oxirgi GC siklidan keyin har bir xotira taqsimoti protsessorga ko'rinmasligi kafolatlanganligini tushunasizmi? Shuning uchun, bularning barchasi keshda bo'lishi mumkin emas va keyin 100% kafolatlangan sog'inish sodir bo'ladi. Ko'rsatkich bilan ishlaganda, x86 da, registrni xotiradan olib tashlash 1-2 takt tsiklini oladi va bu sodir bo'lishi bilan siz to'laysiz, to'laysiz, to'laysiz, chunki xotira hammasi yoqilgan. NINE kesh - va bu xotirani ajratish narxi. Haqiqiy qiymat.

Boshqacha qilib aytganda, ma'lumotlar tuzilmalarini o'zgartirish eng qiyin narsadir. Keyinchalik unumdorlikni pasaytiradigan noto'g'ri ma'lumotlar tuzilmasini tanlaganingizni tushunganingizdan so'ng, odatda juda ko'p ish qilish kerak, lekin agar buni qilmasangiz, vaziyat yomonlashadi. Avvalo, siz ma'lumotlar tuzilmalari haqida o'ylashingiz kerak, bu muhim. Bu erda asosiy xarajat "Men X ma'lumotlar strukturasini Y ma'lumotlar strukturasiga ko'chirdim, chunki menga Y shakli ko'proq yoqadi" uslubida qo'llanila boshlangan yog'li ma'lumotlar tuzilmalariga to'g'ri keladi. Ammo nusxa ko'chirish operatsiyasi (bu arzonga o'xshaydi) aslida xotiraning o'tkazish qobiliyatini yo'qotadi va bu erda barcha behuda sarflangan vaqt ko'miladi. Agar menda JSON ning ulkan qatori bo‘lsa va uni POJO-larning tuzilgan DOM daraxtiga yoki boshqa biror narsaga aylantirmoqchi bo‘lsam, bu qatorni tahlil qilish va POJO-ni yaratish, keyin esa POJO-ga keyinroq kirish amaliyoti keraksiz xarajatlarga olib keladi - bu arzon emas. Agar siz POJO atrofida ip atrofida yugurganingizdan ko'ra tez-tez yugursangiz. O'z-o'zidan, buning o'rniga, satrning shifrini ochishga urinib ko'rishingiz va uni hech qanday POJOga aylantirmasdan, faqat kerakli narsani olishingiz mumkin. Agar bularning barchasi maksimal ishlash talab qilinadigan yo'lda sodir bo'lsa, siz uchun hech qanday POJO yo'q, siz qandaydir tarzda to'g'ridan-to'g'ri chiziqni qazishingiz kerak.

Nima uchun o'z dasturlash tilingizni yaratasiz

Andrew: Xarajat modelini tushunish uchun siz o'zingizning kichik tilingizni yozishingiz kerakligini aytdingiz ...

Cliff: Til emas, balki kompilyator. Til va kompilyator ikki xil narsadir. Eng muhim farq sizning boshingizda. 

Andrew: Aytgancha, men bilishimcha, siz o'z tillaringizni yaratishda tajriba o'tkazyapsiz. Nima uchun?

Cliff: Chunki men qila olaman! Men yarim nafaqadaman, shuning uchun bu mening sevimli mashg'ulotim. Men butun umrim davomida boshqa odamlarning tillarini qo'llaganman. Men kodlash uslubim ustida ham ko'p ishladim. Shuningdek, men boshqa tillarda muammolarni ko'rganim uchun. Men tanish narsalarni qilishning yaxshiroq yo'llari borligini ko'raman. Va men ulardan foydalanardim. Men o'zimdagi, Java-da, Python-da, boshqa har qanday tilda muammolarni ko'rishdan charchadim. Endi men React Native, JavaScript va Elm-da nafaqa haqida emas, balki faol ish haqida sevimli mashg'ulot sifatida yozaman. Men ham Python-da yozaman va, ehtimol, Java backendlari uchun mashinani o'rganish ustida ishlashni davom ettiraman. Ko'p mashhur tillar mavjud va ularning barchasi qiziqarli xususiyatlarga ega. Har bir inson o'ziga xos tarzda yaxshi va siz bu xususiyatlarning barchasini birlashtirishga harakat qilishingiz mumkin. Shunday qilib, men o'zimni qiziqtirgan narsalarni, tilning xatti-harakatlarini o'rganyapman, oqilona semantikani topishga harakat qilaman. Va hozirgacha men muvaffaqiyatga erishaman! Ayni paytda men xotira semantikasi bilan kurashyapman, chunki men uni C va Java-da bo'lgani kabi, kuchli xotira modeli va yuklar va do'konlar uchun xotira semantikasini olishni xohlayman. Shu bilan birga, Haskelldagi kabi avtomatik turdagi xulosaga ega bo'ling. Bu erda men Haskell tipidagi xulosani C va Java-da xotira ishi bilan aralashtirishga harakat qilyapman. Men, masalan, oxirgi 2-3 oy davomida shunday qilyapman.

Andrew: Agar siz boshqa tillardan yaxshiroq tomonlarni oladigan tilni yaratsangiz, kimdir buning aksini qiladi deb o'ylaysizmi: g'oyalaringizni olib, ulardan foydalaning?

Cliff: Yangi tillar aynan shunday paydo bo'ladi! Nima uchun Java C ga o'xshaydi? Chunki C hamma tushunadigan yaxshi sintaksisga ega edi va Java ushbu sintaksisdan ilhomlanib, tip xavfsizligini, massiv chegaralarini tekshirishni, GCni qo'shdi va ular C dan ba'zi narsalarni yaxshiladilar. Ular o'zlarini qo'shdilar. Ammo ular juda ko'p ilhom olishdi, to'g'rimi? Hamma sizdan oldin kelgan devlarning yelkasida turadi - taraqqiyot shunday bo'ladi.

Andrew: Men tushunganimdek, sizning tilingiz xotirada xavfsiz bo'ladi. Rustdan qarz olish tekshiruvi kabi narsalarni amalga oshirish haqida o'ylab ko'rdingizmi? Unga qaradingizmi, u haqida qanday fikrdasiz?

Cliff: Xo'sh, men C ni ko'p yillar davomida yozyapman, bu malloc va bepul, va butun umrni qo'lda boshqaraman. Bilasizmi, qo'lda boshqariladigan umrning 90-95% bir xil tuzilishga ega. Va buni qo'lda qilish juda va juda og'riqli. Men kompilyator sizga u erda nima sodir bo'layotganini va sizning harakatlaringiz bilan nimaga erishganingizni aytib berishini xohlayman. Ba'zi narsalar uchun qarz tekshiruvi buni qutidan tashqarida qiladi. Va u avtomatik ravishda ma'lumotni ko'rsatishi, hamma narsani tushunishi va hatto bu tushunchani taqdim etish bilan meni yuklamasligi kerak. U hech bo'lmaganda mahalliy qochish tahlilini amalga oshirishi kerak va agar u muvaffaqiyatsiz bo'lsa, u holda umrni tavsiflovchi turdagi izohlarni qo'shishi kerak - va bunday sxema qarzni tekshirgichdan yoki haqiqatan ham mavjud xotira tekshiruvidan ancha murakkabroq. "Hammasi yaxshi" va "Men hech narsani tushunmayapman" o'rtasidagi tanlov - yo'q, yaxshiroq narsa bo'lishi kerak. 
Shunday qilib, C tilida juda ko'p kod yozgan odam sifatida, men umrbod avtomatik boshqaruvni qo'llab-quvvatlash eng muhim narsa deb o'ylayman. Men ham Java qancha xotiradan foydalanishidan to'yganman va asosiy shikoyat GC. Java-da xotirani ajratganingizda, siz oxirgi GC siklida mahalliy bo'lgan xotirani qaytarib olmaysiz. Xotirani boshqarish aniqroq bo'lgan tillarda bunday emas. Agar siz malloc-ga qo'ng'iroq qilsangiz, darhol ishlatilgan xotirani olasiz. Odatda siz xotira bilan vaqtinchalik ishlarni qilasiz va darhol uni qaytarib olasiz. Va u darhol malloc hovuziga qaytadi va keyingi malloc tsikli uni yana tortib oladi. Shuning uchun, haqiqiy xotiradan foydalanish ma'lum bir vaqtda jonli ob'ektlar to'plamiga, shuningdek, oqishlarga kamayadi. Va agar hamma narsa butunlay odobsiz tarzda oqmasa, xotiraning ko'p qismi keshlarda va protsessorda tugaydi va u tezda ishlaydi. Lekin to'g'ri tartibda, to'g'ri joyda malloc va bepul chaqiruv bilan qo'lda xotirani boshqarish juda ko'p talab qiladi. Rust buni o'z-o'zidan to'g'ri hal qila oladi va ko'p hollarda yanada yaxshi ishlashni ta'minlaydi, chunki xotira iste'moli faqat joriy hisoblashgacha qisqartiriladi - xotira bo'shatish uchun keyingi GC tsiklini kutishdan farqli o'laroq. Natijada biz ishlashni yaxshilashning juda qiziqarli usuliga ega bo'ldik. Va juda kuchli - demoqchimanki, men fintech uchun ma'lumotlarni qayta ishlashda shunday ishlarni qildim va bu menga taxminan besh baravar tezlashishga imkon berdi. Bu, ayniqsa, protsessorlar tezlashmagan va biz hali ham yaxshilanishlarni kutayotgan dunyoda juda katta o‘sish.

Ishlash muhandisi martaba

Andrew: Men umuman kasblar haqida ham so'ramoqchiman. Siz HotSpot-da JIT ishingiz bilan mashhurlikka erishdingiz va keyin JVM kompaniyasi bo'lgan Azulga ko'chdingiz. Ammo biz allaqachon dasturiy ta'minotdan ko'ra ko'proq apparat ustida ishlagan edik. Va keyin ular to'satdan Big Data va Machine Learning-ga, keyin esa firibgarlikni aniqlashga o'tishdi. Bu qanday sodir bo'ldi? Bular rivojlanishning juda xilma-xil sohalari.

Cliff: Men anchadan beri dasturlash bilan shug'ullanaman va juda ko'p turli xil darslarni olishga muvaffaq bo'ldim. Odamlar: “Oh, siz Java uchun JIT qilgan odamsiz!” deyishsa, bu har doim kulgili bo'ladi. Ammo bundan oldin men PostScript-ning kloni ustida ishlagan edim - bu til bir vaqtlar Apple lazer printerlari uchun ishlatgan. Va bundan oldin men to'rtinchi tilni amalga oshirdim. Menimcha, men uchun umumiy mavzu - bu vositalarni ishlab chiqish. Butun hayotim davomida men boshqa odamlar o'zlarining ajoyib dasturlarini yozadigan asboblar yasadim. Ammo men operatsion tizimlar, drayverlar, yadro darajasidagi disk raskadrovka dasturlari, operatsion tizimni rivojlantirish uchun tillarni ishlab chiqishda ishtirok etdim, ular ahamiyatsiz boshlangan, ammo vaqt o'tishi bilan tobora murakkablasha boshladi. Ammo asosiy mavzu hali ham asboblarni ishlab chiqishdir. Hayotimning katta qismi Azul va Sun orasida o'tdi va u Java haqida edi. Ammo men Big Data va Machine Learning sohasiga kirganimda, men o'zimning shlyapamni yana qo'ydim va shunday dedim: "Oh, endi bizda ahamiyatsiz muammo bor va juda ko'p qiziqarli narsalar sodir bo'lmoqda va odamlar biror narsa qilmoqdalar." Bu rivojlanishning ajoyib yo'li.

Ha, men taqsimlangan hisoblashni juda yaxshi ko'raman. Mening birinchi ishim reklama loyihasida C kursida talaba bo'lganman. Bu haqiqiy analog analizator tomonidan ishlab chiqarilgan analog OCR uchun ma'lumotlarni to'playdigan Zilog Z80 chiplarida hisoblash tarqatildi. Bu ajoyib va ​​butunlay aqldan ozgan mavzu edi. Ammo muammolar bor edi, ba'zi bir qismi to'g'ri tan olinmadi, shuning uchun siz rasmni olib, uni ko'zlari bilan o'qiy oladigan va u nima deyilganini xabar qila oladigan odamga ko'rsatishingiz kerak edi, shuning uchun ma'lumotlarga ega ishlar bor edi va bu ishlar o'z tillariga ega edi. Bularning barchasini qayta ishlaydigan backend bor edi - Z80s vt100 terminallari bilan parallel ravishda ishlaydi - har bir kishi uchun bitta va Z80da parallel dasturlash modeli mavjud edi. Yulduzli konfiguratsiyadagi barcha Z80-lar tomonidan umumiy xotiraning ba'zi bir qismi; Orqa panel ham baham ko'rilgan va RAMning yarmi tarmoq ichida bo'lingan, qolgan yarmi esa shaxsiy yoki boshqa narsaga ketgan. Umumiy... yarim umumiy xotiraga ega mazmunli murakkab parallel taqsimlangan tizim. Bu qachon edi ... Men hatto eslay olmayman, 80-yillarning o'rtalarida. Ancha vaqt oldin. 
Ha, faraz qilaylik, 30 yil ancha vaqt oldin, taqsimlangan hisoblash bilan bog'liq muammolar ancha vaqtdan beri mavjud bo'lib kelgan, odamlar uzoq vaqtdan beri ular bilan urushib kelishgan. Beowulf-klasterlar. Bunday klasterlar shunday ko'rinadi... Misol uchun: Ethernet bor va sizning tezkor x86 bu Ethernetga ulangan va endi siz soxta umumiy xotirani olishni xohlaysiz, chunki o'sha paytda hech kim taqsimlangan hisoblash kodlashni qila olmadi, bu juda qiyin edi va shuning uchun u erda x86-da himoyalangan xotira sahifalari bilan soxta umumiy xotira edi va agar siz ushbu sahifaga yozgan bo'lsangiz, biz boshqa protsessorlarga agar ular bir xil umumiy xotiraga kirishsa, uni sizdan yuklash kerakligini aytdik va shuning uchun uni qo'llab-quvvatlash protokoli kabi narsa. kesh uyg'unligi paydo bo'ldi va buning uchun dasturiy ta'minot. Qiziqarli tushuncha. Haqiqiy muammo, albatta, boshqa narsa edi. Bularning barchasi ishladi, lekin siz tezda ishlash bilan bog'liq muammolarga duch keldingiz, chunki unumdorlik modellarini hech kim etarli darajada tushunmadi - xotiraga kirishning qanday naqshlari borligi, tugunlar bir-biriga cheksiz ping bermasligiga qanday ishonch hosil qilish kerak va hokazo.

H2O-da men o'ylab topgan narsa shundaki, ishlab chiquvchilarning o'zlari parallellik qayerda yashiringan va qaerda yo'qligini aniqlash uchun mas'uldirlar. Men yuqori samarali kod yozishni oson va sodda qiladigan kodlash modelini o'ylab topdim. Ammo sekin ishlaydigan kodni yozish qiyin, u yomon ko'rinadi. Sekin kod yozishga jiddiy harakat qilishingiz kerak, siz nostandart usullardan foydalanishingiz kerak bo'ladi. Tormozlash kodi birinchi qarashda ko'rinadi. Natijada, siz odatda tez ishlaydigan kod yozasiz, lekin umumiy xotira holatida nima qilish kerakligini tushunishingiz kerak. Bularning barchasi katta massivlar bilan bog'langan va u erdagi xatti-harakatlar parallel Java-dagi uchuvchan bo'lmagan katta massivlarga o'xshaydi. Aytmoqchimanki, ikkita ip parallel massivga yozadi, ulardan biri g'alaba qozonadi, ikkinchisi esa mos ravishda yutqazadi va siz qaysi biri ekanligini bilmaysiz. Agar ular o'zgaruvchan bo'lmasa, unda tartib siz xohlagan narsa bo'lishi mumkin - va bu juda yaxshi ishlaydi. Odamlar, albatta, operatsiyalar tartibi haqida qayg'uradilar, ular o'zgaruvchan narsalarni to'g'ri joylarga qo'yishadi va kerakli joylarda xotira bilan bog'liq ishlash muammolarini kutishadi. Aks holda, ular oddiygina kodni 1 dan N gacha bo'lgan tsikllar ko'rinishida yozadilar, bu erda N bir necha trillionlarni tashkil qiladi, barcha murakkab holatlar avtomatik ravishda parallel bo'ladi degan umidda - va u erda ishlamaydi. Lekin H2O da bu Java ham, Scala ham emas; agar xohlasangiz, uni “Java minus minus” deb hisoblashingiz mumkin. Bu juda aniq dasturlash uslubi bo'lib, oddiy C yoki Java kodini tsikllar va massivlar bilan yozishga o'xshaydi. Ammo shu bilan birga, xotirani terabaytlarda qayta ishlash mumkin. Men hali ham H2O dan foydalanaman. Men uni vaqti-vaqti bilan turli loyihalarda ishlataman - va bu hali ham eng tezkor narsa, raqobatchilardan o'nlab marta tezroq. Agar siz Big Datani ustunli ma'lumotlar bilan ishlayotgan bo'lsangiz, H2O'ni engish juda qiyin.

Texnik qiyinchiliklar

Andrew: Faoliyatingizdagi eng katta qiyinchilik nima edi?

Cliff: Biz masalaning texnik yoki texnik bo'lmagan qismini muhokama qilyapmizmi? Men aytmoqchimanki, eng katta qiyinchiliklar texnik muammolar emas. 
Texnik qiyinchiliklarga kelsak. Men ularni shunchaki mag'lub etdim. Men hatto eng kattasi nima ekanligini bilmayman, lekin juda qiziqlari bor edi, ular juda oz vaqtni, ruhiy kurashni talab qildi. Men Sunga borganimda, men tez kompilyator qilishimga ishonchim komil edi va bir guruh kattalar bunga javoban hech qachon muvaffaqiyatga erisha olmasligimni aytishdi. Lekin men bu yo'ldan bordim, registr ajratuvchisiga kompilyator yozdim va bu juda tez edi. Bu zamonaviy C1 kabi tez edi, lekin o'sha paytda ajratuvchi ancha sekinroq edi va orqaga qarab bu katta ma'lumotlar strukturasi muammosi edi. Menga grafik registr ajratuvchisini yozish uchun kerak edi va men o'sha davrda mavjud bo'lgan va juda muhim bo'lgan kodning ifodaliligi va tezligi o'rtasidagi dilemmani tushunmadim. Ma'lum bo'lishicha, ma'lumotlar strukturasi odatda o'sha paytdagi x86-larda kesh hajmidan oshib ketadi va shuning uchun agar men dastlab registrlarni taqsimlovchi umumiy jitter vaqtining 5-10 foizini ishlaydi deb taxmin qilgan bo'lsam, aslida u shunday bo'lib chiqdi. 50 foiz.

Vaqt o'tishi bilan kompilyator yanada toza va samaraliroq bo'ldi, ko'p hollarda dahshatli kod ishlab chiqarishni to'xtatdi va unumdorlik tobora C kompilyatori ishlab chiqaradigan narsaga o'xshab keta boshladi.Agar, albatta, siz hatto C tezligini ham tezlashtirmaydigan ahmoqona yozmasangiz. . Agar siz C kabi kod yozsangiz, ko'proq hollarda C kabi ishlashga erishasiz. Qanchalik uzoqqa borsangiz, asimptotik ravishda C darajasiga to'g'ri keladigan kodni qanchalik tez-tez olsangiz, registr ajratuvchisi sizning kodingiz tez yoki sekin ishlashidan qat'i nazar, tugallangan narsaga o'xshay boshladi. Yaxshiroq tanlov qilish uchun ajratuvchi ustida ishlashni davom ettirdim. U sekinroq va sekinroq bo'ldi, lekin u boshqa hech kim bardosh bera olmaydigan holatlarda yaxshiroq va yaxshiroq ishladi. Men registrni taqsimlovchiga sho'ng'ishim mumkin edi, u erda bir oylik ishimni ko'mib qo'yaman va to'satdan butun kod 5% tezroq ishlay boshlaydi. Bu vaqt o'tishi bilan sodir bo'ldi va registrlarni taqsimlovchi qandaydir san'at asariga aylandi - hamma uni yaxshi ko'rardi yoki yomon ko'rardi va akademiyadagilar "nega hamma narsa shunday qilingan" mavzusida savollar berishdi. chiziqli skanerlash, va qanday farq bor. Javob hali ham bir xil: grafikni bo'yashga asoslangan taqsimlovchi va bufer kodi bilan juda ehtiyotkorlik bilan ishlash g'alaba quroliga teng, hech kim mag'lub qila olmaydigan eng yaxshi kombinatsiya. Va bu juda aniq bo'lmagan narsa. Tuzuvchi bajaradigan barcha narsalar juda yaxshi o'rganilgan, ammo ular ham san'at darajasiga ko'tarilgan. Men har doim kompilyatorni san'at asariga aylantirishi kerak bo'lgan narsalarni qildim. Ammo bularning hech biri g'ayrioddiy narsa emas edi - registrni taqsimlovchidan tashqari. Hiyla ehtiyot bo'lishdir kesmoq yuk ostida va agar bu sodir bo'lsa (agar qiziqsangiz, batafsilroq tushuntirib bera olaman), demak, siz ishlash jadvalidagi burilish xavfisiz, yanada tajovuzkor tarzda kiritishingiz mumkin. O'sha paytlarda ro'yxatga oluvchi va hushtak bilan osilgan bir qancha to'liq hajmli kompilyatorlar bor edi, ularda registrlarni taqsimlovchilar bor edi, lekin boshqa hech kim buni qila olmadi.

Muammo shundaki, agar siz chizilgan maydonni ko'paytiradigan va ko'paytiradigan usullarni qo'shsangiz, ishlatilgan qiymatlar to'plami registrlar sonidan bir zumda oshib ketadi va siz ularni kesishingiz kerak. Kritik daraja, odatda, ajratuvchi taslim bo'lganda keladi va to'kilish uchun bitta yaxshi nomzod boshqasiga arziydi, siz odatda yovvoyi narsalarni sotasiz. Bu erda kiritishning ahamiyati shundaki, siz qo'ng'iroq qilish va saqlash uchun qo'shimcha xarajatlarning bir qismini yo'qotasiz, siz ichidagi qiymatlarni ko'rishingiz va ularni yanada optimallashtirishingiz mumkin. Inlinening narxi shundan iboratki, juda ko'p sonli jonli qiymatlar hosil bo'ladi va agar sizning registr ajratuvchingiz kerak bo'lgandan ko'proq yonib ketsa, siz darhol yo'qotasiz. Shuning uchun, ko'pchilik taqsimlovchilarda muammo bor: inlining ma'lum bir chiziqni kesib o'tganda, dunyodagi hamma narsa qisqartirila boshlaydi va hosildorlikni hojatxonaga tushirish mumkin. Kompilyatorni amalga oshiradiganlar ba'zi evristika qo'shadilar: masalan, etarlicha katta hajmdan boshlab, inlineni to'xtatish uchun, chunki ajratmalar hamma narsani buzadi. Ishlash grafigidagi burilish shu tarzda hosil bo'ladi - siz inline, inline, unumdorlik asta-sekin o'sib boradi - va keyin bum! - juda ko'p chiziq qo'yganingiz uchun tez jek kabi pastga tushadi. Java paydo bo'lishidan oldin hamma narsa shunday ishlagan. Java ko'proq inliningni talab qiladi, shuning uchun men ajratuvchimni yanada tajovuzkor qilib qo'yishim kerak edi, shunda u ishdan chiqishidan ko'ra tekislanadi va agar siz juda ko'p qatorga kirsangiz, u to'kila boshlaydi, lekin keyin "endi to'kilmaydi" momenti hali ham keladi. Bu qiziq kuzatuv va u menga kutilmaganda keldi, aniq emas, lekin yaxshi natija berdi. Men tajovuzkor inlining oldim va u meni Java va C ishlashi yonma-yon ishlaydigan joylarga olib bordi. Ular juda yaqin - men Java kodini C kodidan va shunga o'xshash narsalardan sezilarli darajada tezroq yoza olaman, lekin o'rtacha, narsalarning katta rasmida ularni taxminan solishtirish mumkin. O'ylaymanki, bu xizmatning bir qismi - bu menga imkon qadar ahmoqona ro'yxatga olishimga imkon beruvchi registrni taqsimlovchi. Men ko'rgan hamma narsani qatorga kiritaman. Bu erda savol ajratuvchi yaxshi ishlaydimi, natija aqlli ishlaydigan kodmi. Bu katta qiyinchilik edi: bularning barchasini tushunish va uni amalga oshirish.

Registrni ajratish va ko'p yadroli haqida bir oz

Владимир: Registrni ajratish kabi muammolar abadiy, cheksiz mavzuga o'xshaydi. Qiziq, istiqbolli ko‘ringan, keyin esa amalda muvaffaqiyatsizlikka uchragan g‘oya bo‘lganmi?

Cliff: Albatta! Registrni taqsimlash - bu NP-to'liq muammoni hal qilish uchun ba'zi evristikalarni topishga harakat qiladigan soha. Va siz hech qachon mukammal yechimga erisha olmaysiz, shunday emasmi? Bu shunchaki imkonsiz. Qarang, "Vaqtdan oldin" kompilyatsiyasi - u ham yomon ishlaydi. Bu erda suhbat ba'zi o'rtacha holatlar haqida. Oddiy ishlash haqida, shuning uchun siz borib, yaxshi odatiy ishlash deb hisoblagan narsani o'lchashingiz mumkin - axir, siz uni yaxshilash ustida ishlayapsiz! Ro'yxatdan o'tish - bu unumdorlikka tegishli mavzu. Birinchi prototipga ega bo'lganingizdan so'ng, u ishlaydi va kerakli narsalarni bo'yaydi, ishlash ishi boshlanadi. Siz yaxshi o'lchashni o'rganishingiz kerak. Nima uchun bu muhim? Agar sizda aniq ma'lumotlar bo'lsa, siz turli sohalarga qarashingiz va ko'rishingiz mumkin: ha, bu erda yordam berdi, lekin bu erda hamma narsa buzildi! Ba'zi yaxshi g'oyalar paydo bo'ladi, siz yangi evristika qo'shasiz va birdan hamma narsa o'rtacha bir oz yaxshiroq ishlay boshlaydi. Yoki u boshlamaydi. Bizning rivojlanishimizni oldingi taqsimlovchidan ajratib turadigan besh foizlik ko'rsatkichlar uchun kurashgan bir qancha holatlarim bor edi. Va har safar shunday ko'rinadi: qaerdadir g'alaba qozonasiz, qaerdadir yutqazasiz. Agar sizda yaxshi ishlashni tahlil qilish vositalari bo'lsa, siz yo'qolgan g'oyalarni topishingiz va ular nima uchun muvaffaqiyatsizlikka uchraganini tushunishingiz mumkin. Ehtimol, hamma narsani avvalgidek qoldirishga arziydi, yoki nozik sozlashga jiddiyroq yondashish yoki tashqariga chiqib, boshqa narsalarni tuzatishga arziydi. Bu juda ko'p narsalar! Men bu ajoyib hack qildim, lekin menga bu ham kerak, bu ham, bu ham kerak - va ularning umumiy kombinatsiyasi ba'zi yaxshilanishlarni beradi. Va yolg'izlar muvaffaqiyatsiz bo'lishi mumkin. Bu NP-to'liq muammolar bo'yicha ishlashning tabiati.

Владимир: Ajratgichlarda rasm chizish kabi narsalar allaqachon hal qilingan muammo ekanligini his qiladi. Gapingizdan kelib chiqib, bu siz uchun hal qilindi, shuning uchun ham bunga arziydimi ...

Cliff: Bu kabi hal qilinmagan. Siz uni "hal qilingan" ga aylantirishingiz kerak. Murakkab muammolar bor va ularni hal qilish kerak. Bu amalga oshirilgach, unumdorlik ustida ishlash vaqti keldi. Siz bu ishga shunga mos ravishda yondashishingiz kerak - benchmarklarni bajaring, ko'rsatkichlarni to'plang, oldingi versiyaga qaytganingizda, eski hackingiz qayta ishlay boshlagan (yoki aksincha, to'xtagan) vaziyatlarni tushuntiring. Va biror narsaga erishmaguningizcha taslim bo'lmang. Yuqorida aytib o'tganimdek, agar ishlamagan ajoyib g'oyalar mavjud bo'lsa, lekin g'oyalar registrlarini taqsimlash sohasida bu taxminan cheksizdir. Siz, masalan, ilmiy nashrlarni o'qishingiz mumkin. Garchi hozir bu soha ancha sekinroq harakatlana boshlagan va yoshligidan ko'ra aniqroq bo'lgan. Biroq, bu sohada ishlayotganlar son-sanoqsiz va ularning barcha g'oyalari sinab ko'rishga arziydi, ularning barchasi qanotlarda kutishmoqda. Agar siz ularni sinab ko'rmaguningizcha, ular qanchalik yaxshi ekanini ayta olmaysiz. Ular sizning ajratuvchingizdagi hamma narsa bilan qanchalik yaxshi integratsiyalashgan, chunki ajratuvchi ko'p ishlarni bajaradi va sizning maxsus taqsimlagichingizdagi ba'zi g'oyalar ishlamaydi, lekin boshqa taqsimlagichda ular oson ishlaydi. Ajratuvchi uchun g'alaba qozonishning asosiy usuli - sekin narsalarni asosiy yo'ldan tashqariga tortib, uni sekin yo'llarning chegaralari bo'ylab bo'linishga majbur qilishdir. Shunday qilib, agar siz GCni ishga tushirishni istasangiz, sekin yo'ldan boring, deoptimizatsiya qiling, istisno qiling va bularning barchasini bilasiz - bular nisbatan kam uchraydi. Va ular juda kam uchraydi, men tekshirdim. Siz qo'shimcha ish qilasiz va bu sekin yo'llardagi ko'plab cheklovlarni olib tashlaydi, lekin bu juda muhim emas, chunki ular sekin va kam sayohat qiladilar. Masalan, null ko'rsatkich - bu hech qachon sodir bo'lmaydi, to'g'rimi? Turli xil narsalar uchun bir nechta yo'llarga ega bo'lishingiz kerak, lekin ular asosiyga xalaqit bermasligi kerak. 

Владимир: Bir vaqtning o'zida minglab yadrolar mavjud bo'lganda, ko'p yadrolilar haqida nima deb o'ylaysiz? Bu foydali narsami?

Cliff: GPU muvaffaqiyati uning juda foydali ekanligini ko'rsatadi!

Владимир: Ular juda ixtisoslashgan. Umumiy maqsadli protsessorlar haqida nima deyish mumkin?

Cliff: Bu Azulning biznes modeli edi. Javob odamlar haqiqatan ham bashorat qilinadigan ishlashni yaxshi ko'rgan davrda qaytib keldi. O'sha paytda parallel kod yozish qiyin edi. H2O kodlash modeli yuqori darajada kengaytirilishi mumkin, ammo u umumiy maqsadli model emas. Ehtimol, GPU dan foydalanishga qaraganda biroz umumiyroq. Biz bunday narsani ishlab chiqishning murakkabligi yoki undan foydalanishning murakkabligi haqida gapiramizmi? Misol uchun, Azul menga qiziqarli darsni o'rgatdi, bu juda aniq bo'lmagan: kichik keshlar normaldir. 

Hayotdagi eng katta qiyinchilik

Владимир: Texnik bo'lmagan qiyinchiliklar haqida nima deyish mumkin?

Cliff: Eng katta qiyinchilik odamlarga mehribon va yaxshi bo'lmaslik edi. Va natijada men doimo o'zimni juda ziddiyatli vaziyatlarda topdim. Men ishlar noto'g'ri ketayotganini bilardim, lekin bu muammolarni qanday hal qilishni bilmasdim va ularni hal qila olmadim. O'nlab yillar davom etgan ko'plab uzoq muddatli muammolar shu tarzda paydo bo'ldi. Java-ning C1 va C2 ​​kompilyatorlariga ega ekanligi buning bevosita natijasidir. Java-da ketma-ket o'n yil davomida ko'p darajali kompilyatsiya mavjud emasligi ham bevosita oqibatdir. Ko'rinib turibdiki, bunday tizim bizga kerak edi, lekin nima uchun u mavjud emasligi aniq emas. Menda bitta muhandis yoki bir guruh muhandislar bilan muammolar bor edi. Bir vaqtlar, men Sunda ish boshlaganimda, men ... Mayli, faqat o'shanda emas, men har doim hamma narsada o'z fikrimga egaman. Va men o'yladimki, siz o'zingizning bu haqiqatingizni qabul qilishingiz va uni boshdan kechirishingiz mumkin. Ayniqsa, men ko'pincha hayratlanarli darajada haq edim. Va agar siz bu yondashuvni yoqtirmasangiz ... ayniqsa, siz aniq noto'g'ri va bema'nilik qilsangiz ... Umuman olganda, bir nechta odam bu muloqot shakliga toqat qila olardi. Garchi ba'zilar men kabi bo'lishi mumkin. Men butun hayotimni meritokratik tamoyillar asosida qurdim. Agar menga noto'g'ri narsani ko'rsatsangiz, men darhol orqaga o'girilib aytaman: bema'nilik aytdingiz. Shu bilan birga, albatta, kechirim so'rayman va bularning barchasini, agar mavjud bo'lsa, yaxshiliklarini qayd etaman va boshqa to'g'ri harakatlarni amalga oshiraman. Boshqa tomondan, men umumiy vaqtning hayratlanarli darajada katta foizi uchun hayratlanarli darajada haqman. Va bu odamlar bilan munosabatlarda unchalik yaxshi ishlamaydi. Men yaxshi bo'lishga intilmayapman, lekin savolni ochiqchasiga beraman. "Bu hech qachon ishlamaydi, chunki bir, ikkita va uchta." Va ular: "Oh!" E'tibor bermaslik yaxshiroq bo'lgan boshqa oqibatlar ham bor edi: masalan, xotinim bilan ajrashishga va undan keyin o'n yillik depressiyaga olib kelganlar.

Qiyinchilik - bu odamlar bilan kurashish, ular siz nima qila olishingiz yoki qila olmaysiz, nima muhim va nima emasligini tushunishlari bilan. Kodlash uslubida ko'plab qiyinchiliklar mavjud edi. Men hali ham juda ko'p kod yozaman va o'sha kunlarda hatto sekinlashishga majbur bo'ldim, chunki men juda ko'p parallel vazifalarni bajarib, ularni bittaga qaratish o'rniga ularni yomon bajarganman. Ortga nazar tashlab, Java JIT buyrug'i, C2 buyrug'i uchun kodning yarmini yozdim. Keyingi eng tez koder yarim sekin, keyingi yarmi sekin yozdi va bu eksponensial pasayish edi. Bu qatordagi ettinchi odam juda, juda sekin edi - bu har doim sodir bo'ladi! Men juda ko'p kodga tegdim. Men kim nima yozganiga qaradim, istisnosiz, men ularning kodiga tikilib qaradim, har birini ko'rib chiqdim va baribir ularning har biriga qaraganda o'zim ko'proq yozishni davom ettirdim. Bu yondashuv odamlar bilan juda yaxshi ishlamaydi. Ba'zilarga bu yoqmaydi. Ularning uddasidan chiqa olmagach, har xil shikoyatlar boshlanadi. Misol uchun, bir marta menga kodlashni to'xtatishni aytishdi, chunki men juda ko'p kod yozdim va bu jamoaga xavf tug'dirdi va bularning barchasi menga hazil bo'lib tuyuldi: do'stim, agar jamoaning qolgan qismi yo'qolib qolsa va men kod yozishni davom ettirsam, siz Faqat yarim jamoalarni yo'qotaman. Boshqa tomondan, agar men kod yozishni davom ettirsam va siz jamoaning yarmini yo'qotsangiz, bu juda yomon boshqaruv kabi ko'rinadi. Men bu haqda hech qachon o'ylamaganman, hech qachon gaplashmaganman, lekin u hali ham miyamda edi. Xayolimda: “Hammangiz meni hazillashyapsizmi?” degan fikr aylanib chiqdi. Shunday qilib, eng katta muammo men va odamlar bilan munosabatlarim edi. Endi men o'zimni ancha yaxshi tushunaman, men uzoq vaqt dasturchilar uchun guruh rahbari bo'lganman va endi odamlarga to'g'ridan-to'g'ri aytaman: bilasizmi, men kimman va siz men bilan muomala qilishingiz kerak bo'ladi - tursam yaxshimi? Bu yerga? Va ular u bilan shug'ullana boshlaganlarida, hamma narsa ishladi. Aslida men yomon ham, yaxshi ham emasman, menda hech qanday yomon niyat yoki xudbin intilishlar yo'q, bu shunchaki mening mohiyatim va men u bilan qandaydir tarzda yashashim kerak.

Andrew: Yaqinda hamma introvertlar uchun o'z-o'zini anglash va umuman yumshoq qobiliyatlar haqida gapira boshladi. Bu haqda nima deya olasiz?

Cliff: Ha, bu men xotinim bilan ajrashganimdan olgan tushuncha va saboq edi. Ajralishdan o'rgangan narsam o'zimni tushunish edi. Shu tariqa men boshqa odamlarni tushuna boshladim. Ushbu o'zaro ta'sir qanday ishlashini tushuning. Bu birin-ketin kashfiyotlarga olib keldi. Men kimligim va nima vakili ekanligim haqida tushuncha bor edi. Men nima qilyapman: yoki men vazifa bilan ovoraman, yoki men nizolardan qochaman yoki boshqa narsa - va bu o'z-o'zini anglash darajasi haqiqatan ham o'zimni nazorat qilishimga yordam beradi. Shundan keyin hamma narsa ancha osonlashadi. Nafaqat o‘zimda, balki boshqa dasturchilarda ham kashf etgan narsam — emotsional zo‘riqish holatida fikrlarni so‘z bilan ifodalay olmaslik. Misol uchun, siz u erda kodlash bilan o'tirasiz, oqim holatida, keyin ular sizning oldingizga yugurib kelishadi va bir narsa buzilganligini va endi sizga nisbatan ekstremal choralar ko'rishini histerika bilan baqira boshlashadi. Va siz bir so'z ayta olmaysiz, chunki siz hissiy stress holatidasiz. Olingan bilimlar sizga ushbu daqiqaga tayyorgarlik ko'rishga, undan omon qolishga va chekinish rejasiga o'tishga imkon beradi, shundan so'ng siz biror narsa qilishingiz mumkin. Shunday qilib, ha, bularning barchasi qanday ishlashini tushuna boshlaganingizda, bu hayotni o'zgartiradigan ulkan voqea. 
Men o'zim to'g'ri so'zlarni topa olmadim, lekin harakatlar ketma-ketligini esladim. Gap shundaki, bu reaktsiya og'zaki bo'lgani kabi jismoniy bo'lib, sizga bo'sh joy kerak. Bunday makon, Zen ma'nosida. Aynan shu narsani tushuntirish kerak, keyin darhol chetga chiqing - sof jismonan uzoqlashing. Men og'zaki sukut saqlasam, vaziyatni hissiy jihatdan qayta ishlay olaman. Adrenalin miyangizga etib, sizni jang yoki parvoz rejimiga o'tkazsa, siz endi hech narsa deya olmaysiz, yo'q - endi siz ahmoq, qamchi muhandissiz, munosib javob berishga yoki hatto hujumni to'xtatishga qodir emassiz va tajovuzkor ozoddir. qayta-qayta hujum qilish. Avval o'zingiz bo'lishingiz, nazoratni tiklashingiz, "jang yoki parvoz" rejimidan chiqishingiz kerak.

Va buning uchun bizga og'zaki bo'shliq kerak. Faqat bo'sh joy. Agar siz umuman biror narsa aytsangiz, unda siz aniq aytishingiz mumkin va keyin borib, o'zingiz uchun "bo'sh joy" toping: parkda sayr qiling, o'zingizni dushga yoping - bu muhim emas. Asosiysi, bu vaziyatdan vaqtincha uzish. Kamida bir necha soniya o'chganingizdan so'ng, boshqaruv qaytib keladi, siz hushyor o'ylay boshlaysiz. "Yaxshi, men qandaydir ahmoq emasman, men ahmoqlik qilmayman, men juda foydali odamman." O'zingizni ishontira olganingizdan so'ng, keyingi bosqichga o'tish vaqti keldi: nima bo'lganini tushunish. Sizga hujum qilishdi, hujum siz kutmagan joydan keldi, bu insofsiz, qabih pistirma edi. Bu yomon. Keyingi qadam - bu hujumchiga nima uchun kerakligini tushunish. Haqiqatan ham, nega? Balki uning o'zi g'azablangani uchunmi? Nega u aqldan ozgan? Misol uchun, u o'zini buzganligi va javobgarlikni o'z zimmasiga olmagani uchunmi? Bu butun vaziyatni ehtiyotkorlik bilan hal qilishning yo'lidir. Ammo bu manevr uchun joy, og'zaki bo'shliqni talab qiladi. Birinchi qadam og'zaki aloqani uzishdir. So'zlar bilan muhokama qilishdan saqlaning. Uni bekor qiling, iloji boricha tezroq keting. Agar bu telefon suhbati bo'lsa, go'shakni qo'ying - bu men sobiq xotinim bilan muloqot qilishdan o'rgangan mahoratim. Agar suhbat yaxshi tomonga o'tmasa, shunchaki "xayr" deb ayting va go'shakni o'chiring. Telefonning narigi tomonidan: "bla blah blah", siz javob berasiz: "ha, xayr!" va go'shakni qo'ying. Siz shunchaki suhbatni tugatasiz. Besh daqiqadan so'ng, oqilona fikrlash qobiliyati sizga qaytib kelganida, siz biroz sovib ketdingiz, hamma narsa, nima bo'lganligi va keyin nima bo'lishi haqida o'ylash mumkin bo'ladi. Va shunchaki his-tuyg'ularga javob berishdan ko'ra, o'ylangan javobni shakllantirishni boshlang. Men uchun o'z-o'zini anglashdagi yutuq hissiy stressda gapira olmasligim edi. Bu holatdan chiqish, qanday javob berish va muammolarni bartaraf etish haqida o'ylash va rejalashtirish - bu siz gapira olmaganingizda to'g'ri qadamlardir. Eng oson yo'li - hissiy stress o'zini namoyon qiladigan vaziyatdan qochish va bu stressda ishtirok etishni to'xtatish. Shundan so'ng siz fikrlash qobiliyatiga ega bo'lasiz, qachonki o'ylasangiz, gapira olasiz va hokazo.

Aytgancha, sudda qarshi advokat sizga buni qilishga harakat qilmoqda - endi nima uchun ekanligi aniq. Chunki u sizni shunday holatga bostirish qobiliyatiga egaki, siz hatto ismingizni talaffuz qila olmaysiz. Haqiqiy ma'noda siz gapira olmaysiz. Agar shunday holat yuz bersa va agar siz o'zingizni og'zaki janglar avj olgan joyda, sud kabi joyda topishingizni bilsangiz, advokatingiz bilan kelishingiz mumkin. Advokat sizni himoya qiladi va og'zaki hujumni to'xtatadi va buni butunlay qonuniy yo'l bilan amalga oshiradi va yo'qolgan Zen maydoni sizga qaytadi. Misol uchun, men oilamga bir necha bor qo'ng'iroq qilishim kerak edi, sudya bu haqda juda samimiy edi, lekin qarshi advokat qichqirdi va menga baqirib yubordi, men hatto bir og'iz so'z ham ololmadim. Bunday hollarda vositachidan foydalanish men uchun eng yaxshi natija beradi. Vositachi uzluksiz oqimda sizga tushadigan barcha bosimni to'xtatadi, siz kerakli Zen maydonini topasiz va u bilan gapirish qobiliyati qaytadi. Bu butun bilim sohasi bo'lib, unda o'rganish kerak bo'lgan ko'p narsa, o'zingizning ichingizda kashf qilish uchun juda ko'p narsa bor va bularning barchasi turli odamlar uchun har xil bo'lgan yuqori darajadagi strategik qarorlarga aylanadi. Ba'zi odamlarda yuqorida tavsiflangan muammolar yo'q; odatda, professional sotuvchi odamlarda bunday muammolar yo'q. So‘z bilan tirikchilik qilayotgan bu odamlar – mashhur qo‘shiqchilar, shoirlar, din peshvolari va siyosatchilarning har doim aytadigan gapi bor. Ularda bunday muammolar yo'q, lekin menda bor.

Andrew: Bu... kutilmagan edi. Ajoyib, biz allaqachon ko'p gaplashdik va suhbatni tugatish vaqti keldi. Biz konferensiyada albatta uchrashamiz va bu muloqotni davom ettira olamiz. Hydrada ko'rishguncha!

Kliff bilan suhbatingizni 2019-yil 11-12-iyul kunlari Sankt-Peterburgda bo‘lib o‘tadigan Hydra 2019 konferensiyasida davom ettirishingiz mumkin. U hisobot bilan keladi "Azul Hardware Transactional Memory tajribasi". Chiptalarni sotib olish mumkin rasmiy saytida.

Manba: www.habr.com

a Izoh qo'shish