Temu bual hebat dengan Cliff Click, bapa kompilasi JIT di Jawa

Temu bual hebat dengan Cliff Click, bapa kompilasi JIT di JawaCliff Click β€” CTO Cratus (penderia IoT untuk penambahbaikan proses), pengasas dan pengasas bersama beberapa syarikat permulaan (termasuk Rocket Realtime School, Neurensic dan H2O.ai) dengan beberapa kejayaan keluar. Cliff menulis penyusun pertamanya pada usia 15 tahun (Pascal untuk TRS Z-80)! Beliau terkenal dengan karyanya mengenai C2 di Jawa (Laut Nodes IR). Pengkompil ini menunjukkan kepada dunia bahawa JIT boleh menghasilkan kod berkualiti tinggi, yang merupakan salah satu faktor kemunculan Java sebagai salah satu platform perisian moden yang utama. Kemudian Cliff membantu Azul Systems membina kerangka utama 864 teras dengan perisian Java tulen yang menyokong jeda GC pada timbunan 500 gigabait dalam masa 10 milisaat. Secara umum, Cliff berjaya mengusahakan semua aspek JVM.

 
Habrapost ini adalah wawancara yang hebat dengan Cliff. Kami akan bercakap mengenai topik berikut:

  • Peralihan kepada pengoptimuman peringkat rendah
  • Bagaimana untuk melakukan pemfaktoran semula yang besar
  • Model Kos
  • Latihan pengoptimuman peringkat rendah
  • Contoh praktikal peningkatan prestasi
  • Mengapa mencipta bahasa pengaturcaraan anda sendiri
  • Kerjaya Jurutera Prestasi
  • Cabaran Teknikal
  • Sedikit tentang peruntukan daftar dan teras berbilang
  • Cabaran terbesar dalam hidup

Temu bual dijalankan oleh:

  • Andrey Satarin daripada Perkhidmatan Web Amazon. Dalam kerjayanya, dia berjaya bekerja dalam projek yang sama sekali berbeza: dia menguji pangkalan data yang diedarkan NewSQL di Yandex, sistem pengesanan awan di Kaspersky Lab, permainan berbilang pemain di Mail.ru dan perkhidmatan untuk mengira harga pertukaran asing di Deutsche Bank. Berminat untuk menguji bahagian belakang berskala besar dan sistem teragih.
  • Vladimir Sitnikov daripada Netcracker. Sepuluh tahun bekerja pada prestasi dan kebolehskalaan NetCracker OS, perisian yang digunakan oleh operator telekom untuk mengautomasikan proses pengurusan peralatan rangkaian dan rangkaian. Berminat dengan isu prestasi Pangkalan Data Java dan Oracle. Pengarang lebih daripada sedozen peningkatan prestasi dalam pemandu rasmi PostgreSQL JDBC.

Peralihan kepada pengoptimuman peringkat rendah

Andrew: Anda adalah nama besar dalam dunia kompilasi JIT, Java, dan kerja prestasi secara umum, bukan? 

Cliff: Macam tu lah!

Andrew: Mari kita mulakan dengan beberapa soalan umum tentang kerja prestasi. Apakah pendapat anda tentang pilihan antara pengoptimuman peringkat tinggi dan peringkat rendah seperti bekerja di peringkat CPU?

Cliff: Ya, semuanya mudah di sini. Kod terpantas ialah kod yang tidak pernah dijalankan. Oleh itu, anda sentiasa perlu bermula dari tahap tinggi, bekerja pada algoritma. Notasi O yang lebih baik akan mengalahkan notasi O yang lebih buruk, melainkan beberapa pemalar yang cukup besar campur tangan. Perkara peringkat rendah pergi terakhir. Biasanya, jika anda telah mengoptimumkan baki timbunan anda dengan cukup baik dan masih terdapat beberapa perkara menarik yang tinggal, itu adalah tahap yang rendah. Tetapi bagaimana untuk bermula dari tahap yang tinggi? Bagaimanakah anda tahu bahawa kerja peringkat tinggi yang mencukupi telah dilakukan? Nah... tidak mungkin. Tiada resipi siap sedia. Anda perlu memahami masalah itu, memutuskan apa yang anda akan lakukan (supaya tidak mengambil langkah yang tidak perlu pada masa hadapan) dan kemudian anda boleh mendedahkan profiler, yang boleh mengatakan sesuatu yang berguna. Pada satu ketika, anda sendiri menyedari bahawa anda telah menyingkirkan perkara yang tidak perlu dan sudah tiba masanya untuk melakukan beberapa penalaan halus peringkat rendah. Ini sememangnya satu jenis seni yang istimewa. Terdapat ramai orang melakukan perkara yang tidak perlu, tetapi bergerak dengan pantas sehingga mereka tidak mempunyai masa untuk bimbang tentang produktiviti. Tetapi ini sehingga soalan itu timbul secara terang-terangan. Biasanya 99% masa tiada siapa yang peduli dengan apa yang saya lakukan, sehinggalah saat perkara penting datang di jalan kritikal yang tiada siapa peduli. Dan di sini semua orang mula mengomel kepada anda tentang "mengapa ia tidak berfungsi dengan sempurna dari awal lagi." Secara umum, sentiasa ada sesuatu yang perlu diperbaiki dalam prestasi. Tetapi 99% daripada masa anda tidak mempunyai petunjuk! Anda hanya cuba membuat sesuatu berfungsi dan dalam proses itu anda mengetahui perkara yang penting. Anda tidak boleh tahu terlebih dahulu bahawa bahagian ini perlu sempurna, jadi, sebenarnya, anda perlu sempurna dalam segala-galanya. Tetapi ini adalah mustahil dan anda tidak melakukannya. Selalu ada banyak perkara yang perlu diperbaiki - dan itu adalah perkara biasa.

Bagaimana untuk melakukan pemfaktoran semula yang besar

Andrew: Bagaimana anda bekerja pada persembahan? Ini adalah masalah silang. Sebagai contoh, pernahkah anda menghadapi masalah yang timbul daripada persimpangan banyak fungsi sedia ada?

Cliff: Saya cuba mengelak. Jika saya tahu prestasi akan menjadi isu, saya memikirkannya sebelum saya memulakan pengekodan, terutamanya dengan struktur data. Tetapi selalunya anda menemui semua ini kemudian. Dan kemudian anda perlu pergi ke langkah yang melampau dan melakukan apa yang saya panggil "tulis semula dan takluk": anda perlu mengambil sekeping yang cukup besar. Sesetengah kod masih perlu ditulis semula kerana masalah prestasi atau perkara lain. Walau apa pun alasan untuk menulis semula kod, hampir selalu lebih baik untuk menulis semula sekeping yang lebih besar daripada sekeping yang lebih kecil. Pada masa ini, semua orang mula gemetar ketakutan: "Ya Tuhanku, anda tidak boleh menyentuh terlalu banyak kod!" Tetapi sebenarnya, pendekatan ini hampir selalu berfungsi dengan lebih baik. Anda perlu segera menangani masalah besar, lukis bulatan besar di sekelilingnya dan katakan: Saya akan menulis semula segala-galanya di dalam bulatan. Sempadan jauh lebih kecil daripada kandungan di dalamnya yang perlu diganti. Dan jika persempadanan sempadan sedemikian membolehkan anda melakukan kerja di dalam dengan sempurna, tangan anda bebas, lakukan apa yang anda mahu. Sebaik sahaja anda memahami masalahnya, proses menulis semula adalah lebih mudah, jadi ambil peluang!
Pada masa yang sama, apabila anda melakukan penulisan semula yang besar dan menyedari bahawa prestasi akan menjadi isu, anda boleh mula bimbang tentangnya dengan serta-merta. Ini biasanya bertukar menjadi perkara mudah seperti "jangan salin data, urus data semudah mungkin, kecilkan." Dalam penulisan semula yang besar, terdapat cara standard untuk meningkatkan prestasi. Dan mereka hampir selalu berputar di sekitar data.

Model Kos

Andrew: Dalam salah satu podcast anda bercakap tentang model kos dalam konteks produktiviti. Bolehkah anda menjelaskan apa yang anda maksudkan dengan ini?

Cliff: Sudah tentu. Saya dilahirkan dalam era apabila prestasi pemproses sangat penting. Dan era ini kembali lagi - nasib bukan tanpa ironi. Saya mula hidup pada zaman mesin lapan-bit; komputer pertama saya berfungsi dengan 256 bait. Betul-betul bait. Semuanya sangat kecil. Arahan perlu dikira, dan semasa kami mula bergerak ke atas timbunan bahasa pengaturcaraan, bahasa mengambil lebih banyak lagi. Terdapat Assembler, kemudian Basic, kemudian C, dan C mengurus banyak butiran, seperti peruntukan daftar dan pemilihan arahan. Tetapi semuanya agak jelas di sana, dan jika saya membuat penunjuk kepada contoh pembolehubah, maka saya akan mendapat beban, dan kos arahan ini diketahui. Perkakasan menghasilkan bilangan kitaran mesin tertentu, jadi kelajuan pelaksanaan perkara yang berbeza boleh dikira hanya dengan menambah semua arahan yang akan anda jalankan. Setiap perbandingan/ujian/cawangan/panggilan/muat/stor boleh ditambah dan berkata: itulah masa pelaksanaan untuk anda. Apabila bekerja untuk meningkatkan prestasi, anda pasti akan memberi perhatian kepada nombor yang sepadan dengan kitaran panas kecil. 
Tetapi sebaik sahaja anda beralih kepada Java, Python dan perkara yang serupa, anda dengan cepat beralih daripada perkakasan peringkat rendah. Berapakah kos untuk memanggil getter di Jawa? Jika JIT dalam HotSpot betul sebaris, ia akan dimuatkan, tetapi jika ia tidak melakukan ini, ia akan menjadi panggilan fungsi. Memandangkan panggilan adalah pada gelung panas, ia akan mengatasi semua pengoptimuman lain dalam gelung itu. Oleh itu, kos sebenar akan lebih tinggi. Dan anda serta-merta kehilangan keupayaan untuk melihat sekeping kod dan memahami bahawa kami harus melaksanakannya dari segi kelajuan jam pemproses, memori dan cache yang digunakan. Semua ini menjadi menarik hanya jika anda benar-benar masuk ke dalam persembahan.
Kini kita mendapati diri kita berada dalam situasi di mana kelajuan pemproses hampir tidak meningkat selama sedekad. Zaman dahulu kembali! Anda tidak lagi boleh mengharapkan prestasi benang tunggal yang baik. Tetapi jika anda tiba-tiba masuk ke pengkomputeran selari, ia adalah sangat sukar, semua orang memandang anda seperti James Bond. Pecutan sepuluh kali ganda di sini biasanya berlaku di tempat di mana seseorang telah mengacaukan sesuatu. Concurrency memerlukan banyak kerja. Untuk mendapatkan kelajuan XNUMXx itu, anda perlu memahami model kos. Apakah dan berapa kosnya? Dan untuk melakukan ini, anda perlu memahami bagaimana lidah sesuai dengan perkakasan asas.
Martin Thompson memilih perkataan yang bagus untuk blognya Simpati Mekanikal! Anda perlu memahami apa yang perkakasan akan lakukan, bagaimana sebenarnya ia akan melakukannya, dan mengapa ia melakukan apa yang ia lakukan pada mulanya. Menggunakan ini, agak mudah untuk mula mengira arahan dan memikirkan ke mana masa pelaksanaan akan pergi. Jika anda tidak mempunyai latihan yang sesuai, anda hanya mencari kucing hitam di dalam bilik gelap. Saya melihat orang mengoptimumkan prestasi sepanjang masa yang tidak tahu apa yang mereka lakukan. Mereka banyak menderita dan tidak membuat banyak kemajuan. Dan apabila saya mengambil sekeping kod yang sama, masukkan beberapa hack kecil dan dapatkan kelajuan lima atau sepuluh kali ganda, ia seperti: baik, itu tidak adil, kami sudah tahu anda lebih baik. Luar biasa. Apa yang saya cakapkan... model kos adalah tentang jenis kod yang anda tulis dan berapa cepat ia berjalan secara purata dalam gambaran besar.

Andrew: Dan bagaimana anda boleh menyimpan kelantangan sedemikian dalam kepala anda? Adakah ini dicapai dengan lebih banyak pengalaman, atau? Dari mana datangnya pengalaman sebegitu?

Cliff: Nah, saya tidak mendapat pengalaman saya dengan cara yang paling mudah. Saya memprogramkan dalam Assembly pada zaman anda boleh memahami setiap arahan. Bunyinya bodoh, tetapi sejak itu set arahan Z80 sentiasa kekal dalam kepala saya, dalam ingatan saya. Saya tidak ingat nama orang dalam masa seminit bercakap, tetapi saya masih ingat kod yang ditulis 40 tahun yang lalu. Ia kelakar, ia kelihatan seperti sindrom "saintis bodoh'.

Latihan pengoptimuman peringkat rendah

Andrew: Adakah terdapat cara yang lebih mudah untuk masuk?

Cliff: Ya dan tidak. Perkakasan yang kita semua gunakan tidak banyak berubah dari semasa ke semasa. Semua orang menggunakan x86, kecuali telefon pintar Arm. Jika anda tidak melakukan beberapa jenis pembenaman tegar, anda melakukan perkara yang sama. Okay, seterusnya. Arahan juga tidak berubah selama berabad-abad. Anda perlu pergi dan menulis sesuatu dalam Assembly. Tidak banyak, tetapi cukup untuk mula memahami. Anda tersenyum, tetapi saya bercakap dengan serius. Anda perlu memahami korespondensi antara bahasa dan perkakasan. Selepas itu anda perlu pergi dan menulis sedikit dan membuat penyusun mainan kecil untuk bahasa mainan kecil. Seperti mainan bermakna ia perlu dibuat dalam masa yang munasabah. Ia boleh menjadi sangat mudah, tetapi ia mesti menghasilkan arahan. Tindakan menjana arahan akan membantu anda memahami model kos untuk jambatan antara kod peringkat tinggi yang ditulis semua orang dan kod mesin yang dijalankan pada perkakasan. Surat-menyurat ini akan dibakar ke dalam otak pada masa penyusun ditulis. Malah penyusun yang paling mudah. Selepas itu, anda boleh mula melihat Java dan hakikat bahawa jurang semantiknya jauh lebih dalam, dan lebih sukar untuk membina jambatan di atasnya. Di Jawa, adalah lebih sukar untuk memahami sama ada jambatan kami menjadi baik atau buruk, apa yang akan menyebabkannya runtuh dan apa yang tidak. Tetapi anda memerlukan beberapa jenis titik permulaan di mana anda melihat kod dan memahami: "ya, pengambil ini harus diselaraskan setiap kali." Dan kemudian ternyata kadang-kadang ini berlaku, kecuali untuk keadaan apabila kaedah menjadi terlalu besar, dan JIT mula menyelitkan segala-galanya. Prestasi tempat sedemikian boleh diramalkan serta-merta. Biasanya getter berfungsi dengan baik, tetapi kemudian anda melihat gelung panas yang besar dan menyedari bahawa terdapat beberapa panggilan fungsi yang terapung di sana yang tidak tahu apa yang mereka lakukan. Inilah masalah dengan penggunaan getter yang meluas, sebab mengapa mereka tidak sebaris adalah kerana tidak jelas sama ada mereka adalah pengambil. Jika anda mempunyai asas kod yang sangat kecil, anda hanya boleh mengingatinya dan kemudian berkata: ini adalah pengambil, dan ini adalah penetap. Dalam pangkalan kod yang besar, setiap fungsi menjalani sejarahnya sendiri, yang, secara umum, tidak diketahui oleh sesiapa pun. Profiler mengatakan bahawa kita kehilangan 24% masa pada beberapa gelung dan untuk memahami apa yang dilakukan gelung ini, kita perlu melihat setiap fungsi di dalamnya. Adalah mustahil untuk memahami ini tanpa mengkaji fungsi, dan ini secara serius melambatkan proses pemahaman. Itulah sebabnya saya tidak menggunakan getter dan setter, saya telah mencapai tahap yang baru!
Di mana untuk mendapatkan model kos? Nah, anda boleh membaca sesuatu, sudah tentu... Tetapi saya fikir cara terbaik adalah untuk bertindak. Membuat penyusun kecil akan menjadi cara terbaik untuk memahami model kos dan memasukkannya ke dalam kepala anda sendiri. Pengkompil kecil yang sesuai untuk pengaturcaraan gelombang mikro adalah tugas untuk pemula. Maksud saya, jika anda sudah mempunyai kemahiran pengaturcaraan, maka itu sudah memadai. Semua perkara ini seperti menghuraikan rentetan yang anda miliki sebagai sejenis ungkapan algebra, mengekstrak arahan untuk operasi matematik dari sana dalam susunan yang betul, mengambil nilai yang betul dari daftar - semua ini dilakukan sekaligus. Dan semasa anda melakukannya, ia akan dicetak dalam otak anda. Saya rasa semua orang tahu apa yang dilakukan oleh pengkompil. Dan ini akan memberi pemahaman tentang model kos.

Contoh praktikal peningkatan prestasi

Andrew: Apa lagi yang perlu anda perhatikan semasa mengusahakan produktiviti?

Cliff: Struktur data. By the way, ya, saya sudah lama tidak mengajar kelas ini... Sekolah Roket. Ia menyeronokkan, tetapi ia memerlukan banyak usaha, dan saya juga mempunyai kehidupan! OKEY. Oleh itu, dalam salah satu kelas yang besar dan menarik, "Ke mana perginya prestasi anda," saya memberi pelajar contoh: dua setengah gigabait data fintech telah dibaca daripada fail CSV dan kemudian mereka perlu mengira bilangan produk yang dijual . Data pasaran semak biasa. Paket UDP ditukar kepada format teks sejak tahun 70-an. Chicago Mercantile Exchange - segala macam perkara seperti mentega, jagung, kacang soya, perkara seperti itu. Adalah perlu untuk mengira produk ini, bilangan urus niaga, jumlah purata pergerakan dana dan barangan, dsb. Ia adalah matematik perdagangan yang agak mudah: cari kod produk (iaitu 1-2 aksara dalam jadual cincang), dapatkan amaun, tambahkannya pada salah satu set dagangan, tambah volum, tambah nilai dan beberapa perkara lain. Matematik yang sangat mudah. Pelaksanaan mainan adalah sangat mudah: semuanya ada dalam fail, saya membaca fail dan bergerak melaluinya, membahagikan rekod individu ke dalam rentetan Java, mencari perkara yang diperlukan di dalamnya dan menambahnya mengikut matematik yang diterangkan di atas. Dan ia berfungsi pada kelajuan rendah.

Dengan pendekatan ini, jelas apa yang berlaku, dan pengkomputeran selari tidak akan membantu, bukan? Ternyata peningkatan lima kali ganda dalam prestasi boleh dicapai hanya dengan memilih struktur data yang betul. Dan ini mengejutkan pengaturcara yang berpengalaman! Dalam kes khusus saya, silapnya ialah anda tidak sepatutnya membuat peruntukan memori dalam gelung panas. Nah, ini bukan keseluruhan kebenaran, tetapi secara umum - anda tidak sepatutnya menyerlahkan "sekali dalam X" apabila X cukup besar. Apabila X ialah dua setengah gigabait, anda tidak seharusnya memperuntukkan apa-apa "sekali setiap huruf", atau "sekali setiap baris", atau "sekali setiap medan", apa-apa seperti itu. Di sinilah masa dihabiskan. Bagaimana ini berfungsi? Bayangkan saya membuat panggilan String.split() atau BufferedReader.readLine(). Readline membuat rentetan daripada set bait yang datang melalui rangkaian, sekali untuk setiap baris, untuk setiap satu daripada ratusan juta baris. Saya mengambil baris ini, menghuraikannya dan membuangnya. Mengapa saya membuangnya - baik, saya sudah memprosesnya, itu sahaja. Jadi, untuk setiap bait yang dibaca daripada 2.7G ini, dua aksara akan ditulis dalam baris, iaitu, sudah 5.4G, dan saya tidak memerlukannya untuk apa-apa lagi, jadi ia dibuang. Jika anda melihat lebar jalur memori, kami memuatkan 2.7G yang melalui memori dan bas memori dalam pemproses, dan kemudian dua kali lebih banyak dihantar ke talian yang terletak dalam ingatan, dan semua ini rosak apabila setiap baris baru dicipta. Tetapi saya perlu membacanya, perkakasan membacanya, walaupun semuanya rosak kemudian. Dan saya perlu menuliskannya kerana saya mencipta baris dan cache penuh - cache tidak dapat menampung 2.7G. Jadi, untuk setiap bait yang saya baca, saya membaca dua bait lagi dan menulis dua bait lagi, dan pada akhirnya ia mempunyai nisbah 4:1 - dalam nisbah ini kita membazirkan lebar jalur memori. Dan kemudian ternyata bahawa jika saya lakukan String.split() – ini bukan kali terakhir saya melakukan ini, mungkin ada lagi 6-7 medan di dalamnya. Jadi kod klasik membaca CSV dan kemudian menghuraikan rentetan menghasilkan pembaziran lebar jalur memori kira-kira 14:1 berbanding dengan perkara yang sebenarnya anda ingin miliki. Jika anda membuang pilihan ini, anda boleh mendapatkan kelajuan lima kali ganda.

Dan ia tidak begitu sukar. Jika anda melihat kod dari sudut yang betul, semuanya menjadi agak mudah apabila anda menyedari masalahnya. Anda tidak sepatutnya berhenti memperuntukkan memori sama sekali: satu-satunya masalah ialah anda memperuntukkan sesuatu dan ia serta-merta mati, dan sepanjang jalan ia membakar sumber penting, yang dalam kes ini adalah lebar jalur memori. Dan semua ini mengakibatkan penurunan dalam produktiviti. Pada x86 anda biasanya perlu membakar kitaran pemproses secara aktif, tetapi di sini anda membakar semua memori lebih awal. Penyelesaiannya adalah untuk mengurangkan jumlah pelepasan. 
Bahagian lain masalahnya ialah jika anda menjalankan profiler apabila jalur memori kehabisan, tepat apabila ia berlaku, anda biasanya menunggu cache kembali kerana ia penuh dengan sampah yang baru anda hasilkan, semua baris itu. Oleh itu, setiap beban atau operasi kedai menjadi perlahan, kerana ia membawa kepada kehilangan cache - keseluruhan cache menjadi perlahan, menunggu sampah meninggalkannya. Oleh itu, pemprofil hanya akan menunjukkan bunyi rawak hangat yang disapu sepanjang keseluruhan gelung - tidak akan ada arahan panas yang berasingan atau tempat dalam kod. Hanya bunyi bising. Dan jika anda melihat kitaran GC, semuanya adalah Generasi Muda dan sangat pantas - maksimum mikrosaat atau milisaat. Lagipun, semua memori ini mati serta-merta. Anda memperuntukkan berbilion gigabait, dan dia memotongnya, dan memotongnya, dan memotongnya lagi. Semua ini berlaku dengan cepat. Ternyata terdapat kitaran GC yang murah, bunyi hangat sepanjang keseluruhan kitaran, tetapi kami ingin mendapatkan kelajuan 5x ganda. Pada masa ini, sesuatu harus menutup di kepala anda dan berbunyi: "mengapa ini?!" Limpahan jalur memori tidak dipaparkan dalam penyahpepijat klasik; anda perlu menjalankan penyahpepijat kaunter prestasi perkakasan dan melihatnya sendiri dan terus. Tetapi ini tidak boleh disyaki secara langsung daripada ketiga-tiga gejala ini. Gejala ketiga ialah apabila anda melihat perkara yang anda serlahkan, tanya pemprofil, dan dia menjawab: "Anda membuat satu bilion baris, tetapi GC bekerja secara percuma." Sebaik sahaja ini berlaku, anda menyedari bahawa anda telah mencipta terlalu banyak objek dan membakar keseluruhan lorong memori. Terdapat cara untuk memikirkan perkara ini, tetapi ia tidak jelas. 

Masalahnya adalah dalam struktur data: struktur kosong yang mendasari semua yang berlaku, ia terlalu besar, ia adalah 2.7G pada cakera, jadi membuat salinan perkara ini sangat tidak diingini - anda mahu memuatkannya dari penimbal bait rangkaian dengan segera ke dalam daftar, supaya tidak membaca-menulis ke baris berulang-alik lima kali. Malangnya, Java tidak memberikan anda perpustakaan sedemikian sebagai sebahagian daripada JDK secara lalai. Tetapi ini remeh, bukan? Pada asasnya, ini ialah 5-10 baris kod yang akan digunakan untuk melaksanakan pemuat rentetan buffer anda sendiri, yang mengulangi gelagat kelas rentetan, sambil menjadi pembalut di sekeliling penimbal bait yang mendasari. Akibatnya, ternyata anda bekerja hampir seolah-olah dengan rentetan, tetapi sebenarnya penunjuk kepada penimbal bergerak ke sana, dan bait mentah tidak disalin di mana-mana, dan dengan itu penimbal yang sama digunakan semula berulang kali, dan sistem pengendalian berbesar hati untuk mengambil sendiri perkara yang direka bentuk untuknya, seperti penimbalan dua kali tersembunyi bagi penimbal bait ini dan anda tidak lagi mengisar melalui aliran data yang tidak perlu yang tidak berkesudahan. Ngomong-ngomong, adakah anda faham bahawa apabila bekerja dengan GC, ia dijamin bahawa setiap peruntukan memori tidak akan dapat dilihat oleh pemproses selepas kitaran GC yang terakhir? Oleh itu, semua ini tidak mungkin berada dalam cache, dan kemudian kehilangan dijamin 100% berlaku. Apabila bekerja dengan penunjuk, pada x86, penolakan daftar daripada memori mengambil masa 1-2 kitaran jam, dan sebaik sahaja ini berlaku, anda membayar, membayar, membayar, kerana ingatan semuanya aktif SEMBILAN cache – dan ini ialah kos peruntukan memori. Nilai sebenar.

Dalam erti kata lain, struktur data adalah perkara yang paling sukar untuk diubah. Dan apabila anda menyedari bahawa anda telah memilih struktur data yang salah yang akan membunuh prestasi di kemudian hari, biasanya terdapat banyak kerja yang perlu dilakukan, tetapi jika anda tidak melakukannya, keadaan akan menjadi lebih teruk. Pertama sekali, anda perlu memikirkan struktur data, ini penting. Kos utama di sini adalah pada struktur data gemuk, yang mula digunakan dalam gaya "Saya menyalin struktur data X ke dalam struktur data Y kerana saya lebih suka bentuk Y." Tetapi operasi penyalinan (yang kelihatan murah) sebenarnya membazirkan lebar jalur memori dan di situlah semua masa pelaksanaan yang terbuang itu terkubur. Jika saya mempunyai rentetan gergasi JSON dan saya mahu mengubahnya menjadi pokok DOM berstruktur POJO atau sesuatu, operasi menghurai rentetan itu dan membina POJO, dan kemudian mengakses POJO semula kemudian, akan mengakibatkan kos yang tidak perlu - ia tidak murah. Kecuali jika anda berlari mengelilingi POJO dengan lebih kerap daripada anda berlari mengelilingi rentetan. Sebaliknya, anda boleh cuba menyahsulit rentetan dan mengekstrak hanya apa yang anda perlukan dari sana, tanpa mengubahnya menjadi mana-mana POJO. Jika semua ini berlaku pada laluan dari mana prestasi maksimum diperlukan, tiada POJO untuk anda, anda perlu menggali terus ke dalam talian.

Mengapa mencipta bahasa pengaturcaraan anda sendiri

Andrew: Anda berkata bahawa untuk memahami model kos, anda perlu menulis bahasa kecil anda sendiri...

Cliff: Bukan bahasa, tetapi penyusun. Bahasa dan pengkompil adalah dua perkara yang berbeza. Perbezaan yang paling penting adalah dalam kepala anda. 

Andrew: By the way, setakat yang saya tahu, anda sedang bereksperimen dengan mencipta bahasa anda sendiri. Untuk apa?

Cliff: Kerana saya boleh! Saya separuh bersara, jadi ini hobi saya. Saya telah melaksanakan bahasa orang lain sepanjang hidup saya. Saya juga banyak bekerja pada gaya pengekodan saya. Dan juga kerana saya melihat masalah dalam bahasa lain. Saya nampak ada cara yang lebih baik untuk melakukan perkara biasa. Dan saya akan menggunakannya. Saya hanya bosan melihat masalah dalam diri saya, dalam Java, dalam Python, dalam mana-mana bahasa lain. Saya kini menulis dalam React Native, JavaScript dan Elm sebagai hobi yang bukan tentang persaraan, tetapi tentang kerja aktif. Saya juga menulis dalam Python dan, kemungkinan besar, akan terus bekerja pada pembelajaran mesin untuk backend Java. Terdapat banyak bahasa popular dan semuanya mempunyai ciri yang menarik. Setiap orang adalah baik dengan cara mereka sendiri dan anda boleh cuba menggabungkan semua ciri ini. Jadi, saya sedang mengkaji perkara yang menarik minat saya, tingkah laku bahasa, cuba menghasilkan semantik yang munasabah. Dan setakat ini saya berjaya! Pada masa ini saya sedang bergelut dengan semantik memori, kerana saya ingin memilikinya seperti dalam C dan Java, dan mendapatkan model memori yang kuat dan semantik memori untuk beban dan kedai. Pada masa yang sama, mempunyai inferens jenis automatik seperti dalam Haskell. Di sini, saya cuba mencampurkan inferens jenis seperti Haskell dengan kerja memori dalam kedua-dua C dan Java. Inilah yang saya lakukan selama 2-3 bulan lepas, sebagai contoh.

Andrew: Jika anda membina bahasa yang mengambil aspek yang lebih baik daripada bahasa lain, adakah anda fikir seseorang akan melakukan sebaliknya: ambil idea anda dan gunakannya?

Cliff: Beginilah cara bahasa baharu muncul! Mengapa Java serupa dengan C? Kerana C mempunyai sintaks yang baik yang semua orang fahami dan Java diilhamkan oleh sintaks ini, menambahkan keselamatan jenis, semakan sempadan tatasusunan, GC, dan mereka juga menambah baik beberapa perkara daripada C. Mereka menambah sendiri. Tetapi mereka banyak terinspirasi, bukan? Semua orang berdiri di atas bahu gergasi yang datang sebelum anda - begitulah kemajuan dibuat.

Andrew: Seperti yang saya faham, bahasa anda akan selamat dalam ingatan. Pernahkah anda terfikir untuk melaksanakan sesuatu seperti pemeriksa pinjaman daripada Rust? Pernahkah anda melihatnya, apa pendapat anda tentang dia?

Cliff: Baiklah, saya telah menulis C selama berabad-abad, dengan semua ini malloc dan percuma, dan mengurus seumur hidup secara manual. Anda tahu, 90-95% masa hayat yang dikawal secara manual mempunyai struktur yang sama. Dan ia sangat, sangat menyakitkan untuk melakukannya secara manual. Saya ingin pengkompil memberitahu anda apa yang berlaku di sana dan apa yang anda capai dengan tindakan anda. Untuk beberapa perkara, pemeriksa pinjaman melakukan perkara ini di luar kotak. Dan ia sepatutnya secara automatik memaparkan maklumat, memahami segala-galanya, dan tidak membebankan saya dengan menyampaikan pemahaman ini. Ia mesti melakukan sekurang-kurangnya analisis pelarian tempatan, dan hanya jika ia gagal, maka ia perlu menambah anotasi jenis yang akan menerangkan seumur hidup - dan skema sedemikian jauh lebih kompleks daripada penyemak pinjaman, atau sememangnya mana-mana penyemak memori sedia ada. Pilihan antara "semuanya baik-baik saja" dan "Saya tidak faham apa-apa" - tidak, mesti ada yang lebih baik. 
Jadi, sebagai seseorang yang telah menulis banyak kod dalam C, saya berpendapat bahawa mempunyai sokongan untuk kawalan seumur hidup automatik adalah perkara yang paling penting. Saya juga bosan dengan berapa banyak Java menggunakan memori dan aduan utama ialah GC. Apabila anda memperuntukkan memori dalam Java, anda tidak akan mendapatkan semula memori yang setempat pada kitaran GC terakhir. Ini tidak berlaku dalam bahasa dengan pengurusan memori yang lebih tepat. Jika anda memanggil malloc, anda akan mendapat memori yang biasanya baru sahaja digunakan. Biasanya anda melakukan beberapa perkara sementara dengan ingatan dan segera mengembalikannya semula. Dan ia segera kembali ke kolam malloc, dan kitaran malloc seterusnya menariknya keluar semula. Oleh itu, penggunaan memori sebenar dikurangkan kepada set objek hidup pada masa tertentu, ditambah dengan kebocoran. Dan jika semuanya tidak bocor dengan cara yang benar-benar tidak senonoh, kebanyakan memori berakhir dalam cache dan pemproses, dan ia berfungsi dengan cepat. Tetapi memerlukan banyak pengurusan memori manual dengan malloc dan dipanggil percuma dalam susunan yang betul, di tempat yang betul. Karat boleh mengendalikan ini dengan betul sendiri, dan dalam banyak kes memberikan prestasi yang lebih baik, kerana penggunaan memori dikecilkan kepada hanya pengiraan semasa - berbanding menunggu kitaran GC seterusnya untuk membebaskan memori. Hasilnya, kami mendapat cara yang sangat menarik untuk meningkatkan prestasi. Dan agak berkuasa - Maksud saya, saya melakukan perkara sedemikian semasa memproses data untuk fintech, dan ini membolehkan saya mendapatkan kelajuan kira-kira lima kali. Itu adalah rangsangan yang cukup besar, terutamanya dalam dunia di mana pemproses tidak menjadi lebih pantas dan kami masih menunggu penambahbaikan.

Kerjaya Jurutera Prestasi

Andrew: Saya juga ingin bertanya tentang kerjaya secara umum. Anda menjadi terkenal dengan kerja JIT anda di HotSpot dan kemudian berpindah ke Azul, yang juga merupakan syarikat JVM. Tetapi kami sudah bekerja lebih pada perkakasan daripada perisian. Dan kemudian mereka tiba-tiba beralih kepada Data Besar dan Pembelajaran Mesin, dan kemudian kepada pengesanan penipuan. Bagaimana ini berlaku? Ini adalah bidang pembangunan yang sangat berbeza.

Cliff: Saya telah membuat pengaturcaraan untuk masa yang agak lama dan telah berjaya mengambil banyak kelas yang berbeza. Dan apabila orang berkata: "oh, anda yang melakukan JIT untuk Java!", ia sentiasa lucu. Tetapi sebelum itu, saya sedang mengusahakan klon PostScript - bahasa yang pernah digunakan oleh Apple untuk pencetak lasernya. Dan sebelum itu saya melakukan pelaksanaan bahasa Forth. Saya fikir tema biasa bagi saya ialah pembangunan alat. Sepanjang hidup saya, saya telah membuat alat yang digunakan oleh orang lain untuk menulis program hebat mereka. Tetapi saya juga terlibat dalam pembangunan sistem pengendalian, pemacu, penyahpepijat peringkat kernel, bahasa untuk pembangunan OS, yang bermula dengan remeh, tetapi dari masa ke masa menjadi lebih kompleks. Tetapi topik utama masih pembangunan alat. Sebahagian besar dalam hidup saya berlalu antara Azul dan Sun, dan ia adalah mengenai Jawa. Tetapi apabila saya masuk ke Data Besar dan Pembelajaran Mesin, saya memakai semula topi mewah saya dan berkata, "Oh, sekarang kami mempunyai masalah yang tidak remeh dan terdapat banyak perkara menarik yang berlaku dan orang ramai melakukan sesuatu." Ini adalah laluan pembangunan yang hebat untuk diambil.

Ya, saya sangat menyukai pengkomputeran teragih. Pekerjaan pertama saya ialah sebagai pelajar di C, dalam projek pengiklanan. Ini telah diedarkan pengkomputeran pada cip Zilog Z80 yang mengumpul data untuk OCR analog, yang dihasilkan oleh penganalisis analog sebenar. Ia adalah topik yang keren dan gila. Tetapi terdapat masalah, beberapa bahagian tidak dikenali dengan betul, jadi anda perlu mengeluarkan gambar dan menunjukkannya kepada orang yang sudah boleh membaca dengan mata mereka dan melaporkan apa yang dikatakannya, dan oleh itu terdapat pekerjaan dengan data, dan pekerjaan ini mempunyai bahasa sendiri. Terdapat bahagian belakang yang memproses semua ini - Z80 berjalan selari dengan terminal vt100 berjalan - satu bagi setiap orang, dan terdapat model pengaturcaraan selari pada Z80. Beberapa bahagian memori biasa yang dikongsi oleh semua Z80 dalam konfigurasi bintang; Pesawat belakang juga dikongsi, dan separuh daripada RAM telah dikongsi dalam rangkaian, dan separuh lagi adalah peribadi atau pergi ke sesuatu yang lain. Sistem edaran selari yang kompleks yang bermakna dengan memori kongsi... separa kongsi. Bilakah ini... Saya tidak ingat, di suatu tempat pada pertengahan 80-an. Agak lama dahulu. 
Ya, anggap 30 tahun sudah lama dahulu. Masalah berkaitan pengkomputeran teragih telah wujud sejak sekian lama; orang ramai telah lama berperang dengan Beowulf-kelompok. Kelompok sedemikian kelihatan seperti... Contohnya: terdapat Ethernet dan x86 pantas anda disambungkan ke Ethernet ini, dan kini anda ingin mendapatkan memori kongsi palsu, kerana tiada siapa yang boleh melakukan pengekodan pengkomputeran teragih ketika itu, ia terlalu sukar dan oleh itu terdapat adalah memori kongsi palsu dengan halaman memori perlindungan pada x86, dan jika anda menulis ke halaman ini, maka kami memberitahu pemproses lain bahawa jika mereka mengakses memori kongsi yang sama, ia perlu dimuatkan daripada anda, dan dengan itu sesuatu seperti protokol untuk menyokong keselarasan cache muncul dan perisian untuk ini. Konsep yang menarik. Masalah sebenar, tentu saja, adalah sesuatu yang lain. Semua ini berjaya, tetapi anda dengan cepat mendapat masalah prestasi, kerana tiada siapa yang memahami model prestasi pada tahap yang cukup baik - apakah corak akses memori yang ada, bagaimana untuk memastikan bahawa nod tidak saling ping tanpa henti, dan sebagainya.

Apa yang saya temukan dalam H2O ialah pembangun sendiri yang bertanggungjawab untuk menentukan di mana paralelisme tersembunyi dan di mana ia tidak. Saya menghasilkan model pengekodan yang menjadikan penulisan kod berprestasi tinggi mudah dan ringkas. Tetapi menulis kod berjalan perlahan adalah sukar, ia akan kelihatan buruk. Anda perlu serius cuba menulis kod perlahan, anda perlu menggunakan kaedah bukan standard. Kod brek boleh dilihat pada pandangan pertama. Akibatnya, anda biasanya menulis kod yang berjalan pantas, tetapi anda perlu memikirkan apa yang perlu dilakukan dalam kes memori dikongsi. Semua ini terikat kepada tatasusunan besar dan tingkah laku di sana adalah serupa dengan tatasusunan besar tidak meruap dalam Java selari. Maksud saya, bayangkan bahawa dua utas menulis kepada tatasusunan selari, satu daripadanya menang, dan satu lagi, sewajarnya, kalah, dan anda tidak tahu yang mana satu. Jika ia tidak menentu, maka pesanan itu boleh mengikut apa sahaja yang anda mahukan - dan ini berfungsi dengan baik. Orang ramai benar-benar mengambil berat tentang susunan operasi, mereka meletakkan tidak menentu di tempat yang betul, dan mereka menjangkakan masalah prestasi berkaitan memori di tempat yang betul. Jika tidak, mereka hanya akan menulis kod dalam bentuk gelung dari 1 hingga N, di mana N adalah beberapa trilion, dengan harapan semua kes kompleks akan menjadi selari secara automatik - dan ia tidak berfungsi di sana. Tetapi dalam H2O ini bukan Java atau Scala; anda boleh menganggapnya "Java tolak tolak" jika anda mahu. Ini adalah gaya pengaturcaraan yang sangat jelas dan serupa dengan menulis kod C atau Java yang mudah dengan gelung dan tatasusunan. Tetapi pada masa yang sama, memori boleh diproses dalam terabait. Saya masih menggunakan H2O. Saya menggunakannya dari semasa ke semasa dalam projek yang berbeza - dan ia masih merupakan perkara terpantas, berpuluh-puluh kali lebih pantas daripada pesaingnya. Jika anda melakukan Data Besar dengan data kolumnar, sangat sukar untuk mengalahkan H2O.

Cabaran Teknikal

Andrew: Apakah cabaran terbesar anda dalam keseluruhan kerjaya anda?

Cliff: Adakah kita membincangkan bahagian teknikal atau bukan teknikal isu itu? Saya akan katakan cabaran terbesar bukanlah cabaran teknikal. 
Bagi cabaran teknikal pula. Saya hanya mengalahkan mereka. Saya pun tidak tahu apa yang paling besar, tetapi ada beberapa yang cukup menarik yang mengambil masa yang agak lama, perjuangan mental. Apabila saya pergi ke Sun, saya pasti bahawa saya akan membuat penyusun pantas, dan sekumpulan senior berkata sebagai tindak balas bahawa saya tidak akan berjaya. Tetapi saya mengikuti laluan ini, menulis pengkompil ke pengagih daftar, dan ia agak pantas. Ia sepantas C1 moden, tetapi pengalokasinya jauh lebih perlahan pada masa itu, dan apabila dilihat semula, ia adalah masalah struktur data yang besar. Saya memerlukannya untuk menulis pengalokasi daftar grafik dan saya tidak memahami dilema antara ekspresi kod dan kelajuan, yang wujud pada era itu dan sangat penting. Ternyata struktur data biasanya melebihi saiz cache pada x86s pada masa itu, dan oleh itu, jika saya pada mulanya mengandaikan bahawa pengalokasi daftar akan menghasilkan 5-10 peratus daripada jumlah masa jitter, maka pada hakikatnya ia ternyata menjadi 50 peratus.

Apabila masa berlalu, pengkompil menjadi lebih bersih dan lebih cekap, berhenti menjana kod yang mengerikan dalam lebih banyak kes, dan prestasi semakin mula menyerupai apa yang dihasilkan oleh pengkompil C. Melainkan, sudah tentu, anda menulis beberapa omong kosong yang walaupun C tidak mempercepatkan . Jika anda menulis kod seperti C, anda akan mendapat prestasi seperti C dalam lebih banyak kes. Dan semakin jauh anda pergi, semakin kerap anda mendapat kod yang secara asimptotik bertepatan dengan tahap C, pengalokasi daftar mula kelihatan seperti sesuatu yang lengkap... tidak kira sama ada kod anda berjalan pantas atau perlahan. Saya terus mengusahakan pengagih untuk menjadikannya membuat pilihan yang lebih baik. Dia menjadi lebih perlahan dan lebih perlahan, tetapi dia memberikan prestasi yang lebih baik dan lebih baik dalam kes di mana tiada orang lain dapat mengatasinya. Saya boleh menyelam ke dalam pengagih daftar, menguburkan sebulan kerja di sana, dan tiba-tiba keseluruhan kod akan mula melaksanakan 5% lebih cepat. Ini berlaku dari semasa ke semasa dan pengagih daftar menjadi karya seni - semua orang menyukainya atau membencinya, dan orang dari akademi bertanya soalan mengenai topik "mengapa semuanya dilakukan dengan cara ini", mengapa tidak imbasan talian, dan apakah perbezaannya. Jawapannya masih sama: pengalokasi berdasarkan pewarnaan graf serta kerja yang sangat berhati-hati dengan kod penimbal adalah sama dengan senjata kemenangan, gabungan terbaik yang tiada siapa boleh kalahkan. Dan ini adalah perkara yang agak tidak jelas. Segala-galanya yang dilakukan oleh pengkompil di sana adalah perkara yang dikaji dengan baik, walaupun ia juga telah dibawa ke tahap seni. Saya sentiasa melakukan perkara yang sepatutnya menjadikan pengkompil menjadi karya seni. Tetapi semua ini adalah sesuatu yang luar biasa - kecuali untuk pengagih daftar. Caranya ialah berhati-hati mengurangkan di bawah beban dan, jika ini berlaku (saya boleh menerangkan dengan lebih terperinci jika berminat), ini bermakna anda boleh sebaris dengan lebih agresif, tanpa risiko terjebak dalam jadual prestasi. Pada masa itu, terdapat sekumpulan penyusun skala penuh, digantung dengan perhiasan dan wisel, yang mempunyai pengagih daftar, tetapi tiada orang lain yang dapat melakukannya.

Masalahnya ialah jika anda menambah kaedah yang tertakluk kepada inlining, peningkatan dan peningkatan kawasan inlining, set nilai yang digunakan serta-merta mengatasi bilangan daftar, dan anda perlu memotongnya. Tahap kritikal biasanya datang apabila pengagih berputus asa, dan seorang calon yang baik untuk tumpahan bernilai yang lain, anda akan menjual beberapa perkara yang biasanya liar. Nilai inlining di sini ialah anda kehilangan sebahagian daripada overhed, overhed untuk memanggil dan menyimpan, anda boleh melihat nilai di dalam dan boleh mengoptimumkannya lagi. Kos inlining ialah sejumlah besar nilai hidup terbentuk, dan jika pengagih daftar anda terbakar lebih daripada yang diperlukan, anda serta-merta kalah. Oleh itu, kebanyakan pengagih mempunyai masalah: apabila inlining melintasi garisan tertentu, segala-galanya di dunia mula dikurangkan dan produktiviti boleh dibuang ke tandas. Mereka yang melaksanakan pengkompil menambah beberapa heuristik: sebagai contoh, untuk menghentikan inlining, bermula dengan beberapa saiz yang cukup besar, kerana peruntukan akan merosakkan segala-galanya. Beginilah bagaimana kekusutan dalam graf prestasi terbentuk - anda sebaris, sebaris, prestasi perlahan-lahan berkembang - dan kemudian meledak! – ia jatuh seperti bicu pantas kerana anda berbaris terlalu banyak. Ini adalah bagaimana segala-galanya berfungsi sebelum kedatangan Java. Java memerlukan lebih banyak sebaris, jadi saya terpaksa menjadikan pengagih saya lebih agresif supaya ia mendatar daripada ranap, dan jika anda sebaris terlalu banyak, ia mula tumpah, tetapi kemudian detik "tidak lagi tumpah" masih datang. Ini adalah pemerhatian yang menarik dan ia datang kepada saya entah dari mana, tidak jelas, tetapi ia membuahkan hasil yang baik. Saya mengambil inlining yang agresif dan ia membawa saya ke tempat di mana prestasi Java dan C berfungsi bersebelahan. Mereka benar-benar rapat - saya boleh menulis kod Java yang jauh lebih pantas daripada kod C dan perkara seperti itu, tetapi secara purata, dalam gambaran besar sesuatu, mereka hampir setanding. Saya rasa sebahagian daripada merit ini ialah pengagih daftar, yang membolehkan saya sebaris sebodoh mungkin. Saya hanya sebaris semua yang saya lihat. Persoalannya di sini ialah sama ada pengalokasi berfungsi dengan baik, sama ada hasilnya adalah kod yang berfungsi dengan bijak. Ini adalah satu cabaran besar: untuk memahami semua ini dan menjadikannya berkesan.

Sedikit tentang peruntukan daftar dan teras berbilang

Vladimir: Masalah seperti peruntukan daftar kelihatan seperti topik yang kekal dan tidak berkesudahan. Saya tertanya-tanya adakah pernah ada idea yang kelihatan menjanjikan dan kemudiannya gagal dalam amalan?

Cliff: Sudah tentu! Peruntukan daftar ialah kawasan di mana anda cuba mencari beberapa heuristik untuk menyelesaikan masalah NP-lengkap. Dan anda tidak boleh mencapai penyelesaian yang sempurna, bukan? Ini adalah mustahil. Lihat, Kompilasi Mendahului Masa - ia juga tidak berfungsi dengan baik. Perbualan di sini adalah mengenai beberapa kes biasa. Mengenai prestasi biasa, jadi anda boleh pergi dan mengukur sesuatu yang anda fikir adalah prestasi biasa yang baik - lagipun, anda sedang berusaha untuk memperbaikinya! Peruntukan daftar ialah topik mengenai prestasi. Sebaik sahaja anda mempunyai prototaip pertama, ia berfungsi dan melukis apa yang diperlukan, kerja prestasi bermula. Anda perlu belajar mengukur dengan baik. Mengapa ia penting? Jika anda mempunyai data yang jelas, anda boleh melihat kawasan yang berbeza dan melihat: ya, ia membantu di sini, tetapi di situlah segala-galanya rosak! Beberapa idea yang baik muncul, anda menambah heuristik baharu dan secara purata semuanya mula berfungsi sedikit lebih baik. Atau ia tidak bermula. Saya mempunyai banyak kes di mana kami berjuang untuk prestasi lima peratus yang membezakan pembangunan kami daripada pengalokasi sebelumnya. Dan setiap kali ia kelihatan seperti ini: di suatu tempat anda menang, di suatu tempat anda kalah. Jika anda mempunyai alat analisis prestasi yang baik, anda boleh mencari idea yang hilang dan memahami sebab ia gagal. Mungkin berbaloi untuk meninggalkan segala-galanya seperti sedia ada, atau mungkin mengambil pendekatan yang lebih serius untuk menyesuaikan diri, atau keluar dan membetulkan perkara lain. Ia adalah banyak perkara! Saya membuat hack yang hebat ini, tetapi saya juga memerlukan yang ini, dan yang ini, dan yang ini - dan gabungan jumlah mereka memberikan beberapa penambahbaikan. Dan penyendiri boleh gagal. Ini adalah sifat kerja prestasi pada masalah lengkap NP.

Vladimir: Seseorang mendapat perasaan bahawa perkara seperti melukis dalam pengalokasi adalah masalah yang telah diselesaikan. Nah, ia diputuskan untuk anda, berdasarkan apa yang anda katakan, jadi adakah ia berbaloi...

Cliff: Ia tidak diselesaikan sedemikian. Andalah yang mesti mengubahnya menjadi "diselesaikan". Terdapat masalah yang sukar dan ia perlu diselesaikan. Setelah ini selesai, sudah tiba masanya untuk mengusahakan produktiviti. Anda perlu mendekati kerja ini dengan sewajarnya - lakukan penanda aras, kumpulkan metrik, terangkan situasi apabila, apabila anda kembali ke versi sebelumnya, penggodaman lama anda mula berfungsi semula (atau sebaliknya, berhenti). Dan jangan berputus asa sehingga anda mencapai sesuatu. Seperti yang telah saya katakan, jika terdapat idea-idea hebat yang tidak berfungsi, tetapi dalam bidang peruntukan daftar idea ia adalah lebih kurang tidak berkesudahan. Anda boleh, sebagai contoh, membaca penerbitan saintifik. Walaupun kini kawasan ini telah mula bergerak dengan lebih perlahan dan menjadi lebih jelas berbanding zaman mudanya. Walau bagaimanapun, terdapat banyak orang yang bekerja dalam bidang ini dan semua idea mereka patut dicuba, mereka semua menunggu di depan mata. Dan anda tidak boleh memberitahu betapa baiknya mereka melainkan anda mencubanya. Sejauh mana mereka menyepadukan dengan semua yang lain dalam pengalokasi anda, kerana pengalokasi melakukan banyak perkara, dan beberapa idea tidak akan berfungsi dalam pengalokasi khusus anda, tetapi dalam pengalokasi lain mereka akan dengan mudah. Cara utama untuk menang bagi pengagih adalah dengan menarik barang perlahan di luar laluan utama dan memaksanya berpecah di sepanjang sempadan laluan perlahan. Jadi jika anda ingin menjalankan GC, ambil jalan perlahan, nyahoptimumkan, buang pengecualian, semua perkara itu - anda tahu perkara ini agak jarang berlaku. Dan mereka sangat jarang berlaku, saya menyemak. Anda melakukan kerja tambahan dan ia mengalih keluar banyak sekatan pada laluan perlahan ini, tetapi ia tidak begitu penting kerana ia perlahan dan jarang dilalui. Sebagai contoh, penunjuk nol - ia tidak pernah berlaku, bukan? Anda perlu mempunyai beberapa laluan untuk perkara yang berbeza, tetapi ia tidak sepatutnya mengganggu laluan utama. 

Vladimir: Apakah pendapat anda tentang berbilang teras, apabila terdapat beribu-ribu teras sekaligus? Adakah ini satu perkara yang berguna?

Cliff: Kejayaan GPU menunjukkan bahawa ia agak berguna!

Vladimir: Mereka agak khusus. Bagaimana dengan pemproses tujuan umum?

Cliff: Nah, itu adalah model perniagaan Azul. Jawapannya datang kembali dalam era apabila orang sangat menyukai prestasi yang boleh diramal. Sukar untuk menulis kod selari ketika itu. Model pengekodan H2O sangat berskala, tetapi ia bukan model tujuan umum. Mungkin sedikit lebih umum daripada semasa menggunakan GPU. Adakah kita bercakap tentang kerumitan membangunkan perkara sedemikian atau kerumitan menggunakannya? Sebagai contoh, Azul mengajar saya satu pelajaran yang menarik, yang agak tidak jelas: cache kecil adalah perkara biasa. 

Cabaran terbesar dalam hidup

Vladimir: Bagaimana pula dengan cabaran bukan teknikal?

Cliff: Cabaran terbesar adalah untuk tidak menjadi... baik dan baik kepada orang. Dan akibatnya, saya sentiasa mendapati diri saya berada dalam situasi yang sangat konflik. Orang-orang di mana saya tahu perkara-perkara yang berlaku, tetapi tidak tahu bagaimana untuk bergerak ke hadapan dengan masalah itu dan tidak dapat menanganinya. Banyak masalah jangka panjang, berlarutan selama beberapa dekad, timbul dengan cara ini. Hakikat bahawa Java mempunyai penyusun C1 dan C2 adalah akibat langsung daripada ini. Hakikat bahawa tiada kompilasi berbilang peringkat di Jawa selama sepuluh tahun berturut-turut juga merupakan akibat langsung. Adalah jelas bahawa kami memerlukan sistem sedemikian, tetapi tidak jelas mengapa ia tidak wujud. Saya mempunyai masalah dengan seorang jurutera... atau sekumpulan jurutera. Suatu ketika dahulu, semasa saya mula bekerja di Sun, saya... Okay, bukan itu sahaja, saya secara umumnya sentiasa mempunyai pendapat sendiri tentang segala-galanya. Dan saya fikir benar bahawa anda boleh mengambil kebenaran anda ini dan memberitahunya terus. Lebih-lebih lagi kerana saya sangat mengejutkan pada kebanyakan masa. Dan jika anda tidak menyukai pendekatan ini... terutamanya jika anda jelas salah dan melakukan perkara karut... Secara umum, beberapa orang boleh bertolak ansur dengan bentuk komunikasi ini. Walaupun ada yang boleh, seperti saya. Saya telah membina seluruh hidup saya berdasarkan prinsip meritokrasi. Jika anda menunjukkan sesuatu yang salah, saya akan segera berpaling dan berkata: anda berkata karut. Pada masa yang sama, sudah tentu, saya memohon maaf dan semua itu, saya akan perhatikan merit, jika ada, dan mengambil tindakan lain yang betul. Sebaliknya, saya betul-betul mengejutkan tentang peratusan yang sangat besar daripada jumlah masa. Dan ia tidak berfungsi dengan baik dalam hubungan dengan orang ramai. Saya tidak cuba bersikap baik, tetapi saya bertanya soalan itu secara terang-terangan. "Ini tidak akan berjaya, kerana satu, dua dan tiga." Dan mereka seperti, "Oh!" Terdapat akibat lain yang mungkin lebih baik untuk diabaikan: contohnya, akibat yang membawa kepada perceraian daripada isteri saya dan sepuluh tahun kemurungan selepas itu.

Cabaran ialah perjuangan dengan orang ramai, dengan persepsi mereka tentang apa yang anda boleh atau tidak boleh lakukan, apa yang penting dan apa yang tidak. Terdapat banyak cabaran tentang gaya pengekodan. Saya masih menulis banyak kod, dan pada masa itu saya terpaksa memperlahankan kerana saya melakukan terlalu banyak tugasan selari dan melakukannya dengan buruk, dan bukannya menumpukan pada satu. Melihat ke belakang, saya menulis separuh kod untuk arahan Java JIT, arahan C2. Pengekod terpantas seterusnya menulis separuh sebagai perlahan, separuh seterusnya sebagai perlahan, dan ia adalah penurunan eksponen. Orang ketujuh dalam baris ini sangat, sangat perlahan - itu selalu berlaku! Saya menyentuh banyak kod. Saya melihat siapa yang menulis apa, tanpa pengecualian, saya merenung kod mereka, menyemak setiap daripada mereka, dan masih terus menulis lebih banyak diri saya daripada mana-mana daripada mereka. Pendekatan ini tidak begitu berkesan dengan orang ramai. Sesetengah orang tidak suka ini. Dan apabila mereka tidak dapat menanganinya, pelbagai aduan bermula. Sebagai contoh, saya pernah diberitahu untuk menghentikan pengekodan kerana saya menulis terlalu banyak kod dan ia membahayakan pasukan, dan semuanya terdengar seperti jenaka kepada saya: kawan, jika seluruh pasukan hilang dan saya terus menulis kod, anda hanya akan kehilangan separuh pasukan. Sebaliknya, jika saya terus menulis kod dan anda kehilangan separuh pasukan, itu kelihatan seperti pengurusan yang sangat buruk. Saya tidak pernah benar-benar memikirkannya, tidak pernah bercakap mengenainya, tetapi ia masih ada di dalam kepala saya. Fikiran itu berputar di belakang fikiran saya: "Adakah anda semua bergurau dengan saya?" Jadi, masalah terbesar ialah saya dan hubungan saya dengan orang ramai. Sekarang saya memahami diri saya dengan lebih baik, saya adalah ketua pasukan untuk pengaturcara untuk masa yang lama, dan sekarang saya terus memberitahu orang ramai: anda tahu, saya adalah saya, dan anda perlu berurusan dengan saya - adakah tidak mengapa jika saya berdiri di sini? Dan apabila mereka mula menanganinya, semuanya berjaya. Sebenarnya, saya tidak jahat atau baik, saya tidak mempunyai niat buruk atau aspirasi mementingkan diri sendiri, ia hanya intipati saya, dan saya perlu hidup dengannya entah bagaimana.

Andrew: Baru-baru ini semua orang mula bercakap tentang kesedaran diri untuk introvert, dan kemahiran insaniah secara umum. Apa yang anda boleh katakan tentang ini?

Cliff: Ya, itulah pandangan dan pengajaran yang saya dapat daripada penceraian saya dengan isteri saya. Apa yang saya pelajari daripada penceraian itu ialah memahami diri sendiri. Ini adalah bagaimana saya mula memahami orang lain. Fahami cara interaksi ini berfungsi. Ini membawa kepada penemuan satu demi satu. Terdapat kesedaran tentang siapa saya dan apa yang saya wakili. Apa yang saya lakukan: sama ada saya sibuk dengan tugas itu, atau saya mengelak konflik, atau sesuatu yang lain - dan tahap kesedaran diri ini benar-benar membantu mengawal diri saya. Selepas ini semuanya menjadi lebih mudah. Satu perkara yang saya temui bukan sahaja dalam diri saya, tetapi juga dalam pengaturcara lain ialah ketidakupayaan untuk menyatakan fikiran secara lisan apabila anda berada dalam keadaan tekanan emosi. Sebagai contoh, anda sedang duduk di sana mengekod, dalam keadaan mengalir, dan kemudian mereka berlari kepada anda dan mula menjerit histeria bahawa ada sesuatu yang rosak dan kini langkah melampau akan diambil terhadap anda. Dan anda tidak boleh berkata apa-apa kerana anda berada dalam keadaan tekanan emosi. Pengetahuan yang diperoleh membolehkan anda bersedia untuk masa ini, bertahan dan meneruskan ke rancangan berundur, selepas itu anda boleh melakukan sesuatu. Jadi ya, apabila anda mula menyedari bagaimana ia berfungsi, ia adalah peristiwa besar yang mengubah hidup. 
Saya sendiri tidak dapat mencari perkataan yang betul, tetapi saya ingat urutan tindakan. Intinya ialah tindak balas ini adalah sama seperti fizikal seperti lisan, dan anda memerlukan ruang. Ruang sedemikian, dalam pengertian Zen. Inilah yang perlu dijelaskan, dan kemudian segera mengetepikan - secara fizikal semata-mata menjauh. Apabila saya berdiam diri secara lisan, saya boleh memproses keadaan secara emosi. Apabila adrenalin mencapai otak anda, menukar anda ke mod pertarungan atau penerbangan, anda tidak lagi boleh berkata apa-apa, tidak - kini anda seorang yang bodoh, jurutera sebat, tidak mampu memberikan tindak balas yang baik atau menghentikan serangan, dan penyerang bebas untuk menyerang lagi dan lagi. Anda mesti menjadi diri sendiri semula, mendapatkan semula kawalan, keluar daripada mod "berjuang atau melarikan diri".

Dan untuk ini kita memerlukan ruang lisan. Hanya ruang kosong. Sekiranya anda mengatakan apa-apa, maka anda boleh mengatakannya dengan tepat, dan kemudian pergi dan cari "ruang" untuk diri sendiri: pergi berjalan-jalan di taman, kunci diri anda di bilik mandi - tidak mengapa. Perkara utama ialah memutuskan sambungan dari situasi itu buat sementara waktu. Sebaik sahaja anda mematikan sekurang-kurangnya beberapa saat, kawalan kembali, anda mula berfikir dengan waras. "Baiklah, saya bukan jenis yang bodoh, saya tidak melakukan perkara bodoh, saya seorang yang cukup berguna." Sebaik sahaja anda dapat meyakinkan diri sendiri, sudah tiba masanya untuk bergerak ke peringkat seterusnya: memahami apa yang berlaku. Anda telah diserang, serangan itu datang dari tempat yang anda tidak sangka, ia adalah serangan hendap yang tidak jujur ​​dan keji. Ini tidak baik. Langkah seterusnya ialah memahami mengapa penyerang memerlukan ini. Benar-benar mengapa? Mungkin kerana dia sendiri marah? Kenapa dia marah? Sebagai contoh, kerana dia merosakkan dirinya sendiri dan tidak boleh menerima tanggungjawab? Ini adalah cara untuk menangani keseluruhan situasi dengan teliti. Tetapi ini memerlukan ruang untuk manuver, ruang lisan. Langkah pertama ialah memutuskan hubungan lisan. Elakkan perbincangan dengan perkataan. Batalkannya, pergi secepat mungkin. Jika perbualan telefon, tutup sahaja - ini adalah kemahiran yang saya pelajari daripada berkomunikasi dengan bekas isteri saya. Jika perbualan tidak berjalan lancar, ucapkan "selamat tinggal" dan tutup telefon. Dari sisi lain telefon: "bla bla bla", anda menjawab: "ya, selamat tinggal!" dan tutup telefon. Anda hanya menamatkan perbualan. Lima minit kemudian, apabila keupayaan untuk berfikir secara waras kembali kepada anda, anda telah tenang sedikit, ia menjadi mungkin untuk memikirkan segala-galanya, apa yang berlaku dan apa yang akan berlaku seterusnya. Dan mula merumuskan tindak balas yang bernas, bukannya hanya bertindak balas daripada emosi. Bagi saya, kejayaan dalam kesedaran diri adalah hakikat bahawa dalam kes tekanan emosi saya tidak boleh bercakap. Keluar dari keadaan ini, berfikir dan merancang cara untuk bertindak balas dan mengimbangi masalah - ini adalah langkah yang betul dalam kes apabila anda tidak boleh bercakap. Cara paling mudah ialah melarikan diri dari situasi di mana tekanan emosi menjelma sendiri dan hanya berhenti mengambil bahagian dalam tekanan ini. Selepas itu anda boleh berfikir, apabila anda boleh berfikir, anda boleh bercakap, dan seterusnya.

Ngomong-ngomong, di mahkamah, peguam lawan cuba melakukan ini kepada anda - sekarang sudah jelas sebabnya. Kerana dia mempunyai keupayaan untuk menindas anda ke keadaan sedemikian sehingga anda tidak boleh menyebut nama anda, sebagai contoh. Dalam erti kata yang sangat nyata, anda tidak akan dapat bercakap. Jika ini berlaku kepada anda, dan jika anda tahu bahawa anda akan mendapati diri anda berada di tempat di mana pertempuran lisan sedang berlaku, di tempat seperti mahkamah, maka anda boleh datang dengan peguam anda. Peguam akan membela anda dan menghentikan serangan lisan, dan akan melakukannya dengan cara yang benar-benar sah, dan ruang Zen yang hilang akan kembali kepada anda. Sebagai contoh, saya terpaksa menelefon keluarga saya beberapa kali, hakim agak mesra tentang perkara ini, tetapi peguam lawan menjerit dan menjerit kepada saya, saya tidak dapat mendapatkan kata-kata secara tepat. Dalam kes ini, menggunakan mediator paling sesuai untuk saya. Pengantara menghentikan semua tekanan yang mencurah kepada anda dalam aliran berterusan, anda mendapati ruang Zen yang diperlukan, dan dengan itu keupayaan untuk bercakap kembali. Ini adalah seluruh bidang pengetahuan yang terdapat banyak perkara untuk dipelajari, banyak perkara untuk ditemui dalam diri anda, dan semua ini bertukar menjadi keputusan strategik peringkat tinggi yang berbeza untuk orang yang berbeza. Sesetengah orang tidak mempunyai masalah yang diterangkan di atas; biasanya, orang yang merupakan jurujual profesional tidak mengalaminya. Semua orang ini yang mencari rezeki dengan kata-kata - penyanyi terkenal, penyair, pemimpin agama dan ahli politik, mereka sentiasa mempunyai sesuatu untuk dikatakan. Mereka tidak mempunyai masalah seperti itu, tetapi saya ada.

Andrew: Ia adalah... tidak dijangka. Hebat, kami sudah banyak bercakap dan tiba masanya untuk menamatkan temuduga ini. Kami pasti akan bertemu di persidangan itu dan akan dapat meneruskan dialog ini. Jumpa anda di Hydra!

Anda boleh meneruskan perbualan anda dengan Cliff di persidangan Hydra 2019, yang akan diadakan pada 11-12 Julai 2019 di St. Petersburg. Dia akan datang dengan laporan "Pengalaman Memori Transaksi Perkakasan Azul". Tiket boleh dibeli di laman web rasmi.

Sumber: www.habr.com

Tambah komen