- Dalam situasi kontensi tinggi, perbedaan implementasi Mutex terlihat jelas;
pthread_mutex_tdari Cosmopolitan Libc menunjukkan waktu eksekusi lebih singkat dan penggunaan CPU lebih rendah dibanding implementasi utama di Windows dan Linux - Pada pengujian 24-core Threadripper 29070WX di Windows, Cosmopolitan 2,75 kali lebih cepat daripada Microsoft SRWLOCK dan menggunakan sumber daya CPU 18 kali lebih sedikit
- Pada 96-core Threadripper Pro 7995WX di Linux, Cosmopolitan 3 kali lebih cepat daripada glibc dan 11 kali lebih cepat daripada musl libc, dengan selisih waktu CPU yang lebih besar lagi
- Di MacOS M2 Ultra, Apple Libc unggul tipis, sementara Cosmopolitan menggunakan algoritme sederhana yang bergantung pada system call ulock XNU di lingkungan ARM
- Dasar performanya adalah integrasi nsync dari Google; jalur cepat CAS, antrean penunggu, futex/ulock/
WaitOnAddress(), pencegahan starvation, dan desain designated waker menjadi inti utamanya
Metode benchmark Mutex berkontensi
- Pengujian membuat 30 thread, dan setiap thread menaikkan integer global yang sama,
g_chores, sebanyak 100.000 kali - Setiap operasi increment dijalankan di critical section yang sangat kecil di antara
pthread_mutex_lock()danpthread_mutex_unlock() - Nilai diukur dalam mikrodetik dan dibagi menjadi tiga jenis waktu
- wall time: waktu nyata yang dibutuhkan program untuk berjalan, termasuk overhead pembuatan thread dan join
- user time: waktu CPU yang dikonsumsi di ruang pengguna
- system time: waktu CPU yang dikonsumsi di kernel
- Karena banyak thread berjalan paralel, jumlah user time dan system time bisa lebih besar daripada wall time
- Dalam kondisi tanpa kontensi, perbedaan performa antarimplementasi umumnya kecil, tetapi dalam situasi kontensi, perbedaan desain Mutex terlihat besar
Windows: Cosmopolitan lebih cepat daripada SRWLOCK
- Pengujian Windows dilakukan pada 24-core Threadripper 29070WX
- MutexShootout dari Mark Waterman menilai SRWLOCK Windows sebagai implementasi terkuat dalam skenario kontensi tinggi
- Dalam kondisi yang sama,
pthread_mutex_tCosmopolitan mencatat wall time lebih singkat dan penggunaan CPU lebih rendah daripada SRWLOCK
| Implementasi | wall time | user time | system time |
|---|---|---|---|
Cosmopolitan pthread_mutex_t |
148.940µs | 328.125µs | 62.500µs |
| Microsoft SRWLOCK | 410.416µs | 5.515.625µs | 1.640.625µs |
Microsoft CRITICAL_SECTION |
949.187µs | 7.937.500µs | 5.078.125µs |
MSVC 2022 std::mutex |
991.750µs | 12.156.250µs | 4.031.250µs |
| spin lock | 1.165.435µs | 24.515.000µs | 15.000µs |
Cygwin pthread_mutex_t |
9.780.803µs | 1.937.000µs | 6.156.000µs |
- Cosmopolitan Mutex 2,75 kali lebih cepat daripada Microsoft SRWLOCK dan menggunakan 18 kali lebih sedikit sumber daya CPU
- Dibandingkan dengan Cygwin Mutex, yang menyediakan implementasi POSIX di Windows, Cosmopolitan 65 kali lebih cepat
- Dalam use case ini, Cygwin Mutex bahkan menghasilkan hasil yang lebih lambat daripada spin lock
Linux: selisih waktu CPU lebih besar daripada wall time
- Pengujian Linux dilakukan pada 96-core Threadripper Pro 7995WX
| Implementasi | wall time | user time | system time |
|---|---|---|---|
Cosmopolitan pthread_mutex_t |
36.905µs | 44.511µs | 23.492µs |
glibc pthread_mutex_t |
101.353µs | 150.706µs | 2.724.851µs |
| spin lock | 202.423µs | 4.694.749µs | 2.000µs |
Musl libc pthread_mutex_t |
411.013µs | 2.167.898µs | 9.926.850µs |
- Cosmopolitan Mutex 3 kali lebih cepat daripada glibc dan 11 kali lebih cepat daripada musl libc
- Berdasarkan waktu CPU, Cosmopolitan menggunakan 42 kali lebih sedikit daripada glibc dan 178 kali lebih sedikit daripada musl libc
- Pada workload yang mengharuskan semua thread mengerjakan pekerjaan yang diserialisasi, Cosmopolitan bisa terlihat di
htopseolah hanya satu core yang aktif - Dalam situasi yang sama, glibc dan musl libc dapat memenuhi penggunaan CPU secara signifikan, sehingga bebannya lebih besar saat menjalankan banyak pekerjaan di server yang sama
MacOS: Apple Libc unggul tipis
- Pengujian MacOS dilakukan pada M2 Ultra
| Implementasi | wall time | user time | system time |
|---|---|---|---|
| Apple Libc | 52.263µs | 43.202µs | 911.009µs |
Cosmopolitan pthread_mutex_t |
54.700µs | 63.055µs | 1.003.674µs |
- Di MacOS M2 ARM64, Apple Libc sedikit lebih cepat daripada Cosmopolitan Mutex
- Implementasi Mutex umum Cosmopolitan tidak berjalan baik di platform ini
- Di MacOS ARM, Cosmopolitan menggunakan algoritme yang lebih sederhana berdasarkan Futexes Are Tricky dari Ulrich Drepper
- Cara ini menyerahkan sebagian besar pekerjaan berat kepada system call ulock XNU, sehingga pada akhirnya menghasilkan performa yang hampir sama dengan implementasi Apple
Dasar performa: integrasi nsync
- Inti performa Cosmopolitan Mutex adalah integrasi library nsync dari Google
- nsync adalah library dengan 371 star di GitHub, ditulis oleh Mike Burrows dari Google
- Dalam proses integrasi Cosmopolitan, pekerjaan berikut dilakukan
- Menemukan dan memperbaiki bug lama yang belum terdeteksi di fungsi unlock Mutex nsync
- Mem-porting ke operasi atomik C11 di AARCH64 sehingga nsync Mutex berkontensi menjadi 30% lebih cepat daripada upstream nsync
- Menulis ulang integrasi sistem seperti futex agar portabilitas runtime dimungkinkan
- Membuatnya berjalan mulus dengan pembatalan thread POSIX
Cara kerja nsync
- Untuk mendapatkan lock dengan cepat, nsync pertama-tama langsung mencoba CAS(compare and swap) secara optimistis
- Jika gagal mendapatkan lock, thread pemanggil ditambahkan ke doubly linked list para penunggu
- Setiap penunggu memiliki semafornya sendiri pada cache line terpisah dan independen
- Thread yang masuk ke status menunggu tidak lagi menyentuh lock utama
- Ini penting untuk mengurangi overhead komunikasi yang muncul ketika banyak core menyentuh cache line yang sama
- Sebagai latar belakang terkait, ada tautan ke What Every Programmer Should Know About Memory dari Ulrich Drepper
- nsync menggunakan futex milik sistem operasi untuk menidurkan thread
- Di MacOS, futex disebut ulock
- Di Windows,
WaitOnAddress()berperan sebagai futex - Di antara OS yang didukung Cosmo, hanya NetBSD yang tidak memiliki futex; semafor POSIX diimplementasikan di ruang kernel dan membutuhkan file descriptor baru untuk setiap semafor
- nsync menghindari starvation dengan konsep “long wait”
- Jika seorang penunggu telah dibangunkan 30 kali tetapi selalu gagal memperoleh lock secara internal, sebuah bit ditambahkan ke lock agar thread yang belum menunggu tidak bisa memperoleh lock
- Jika bit ini ada, CAS awal thread yang baru masuk akan gagal sampai antrean tunggu sampai batas tertentu dikosongkan
- Use case yang berkontensi pada critical section kecil menjadi lebih cepat dengan konsep designated waker
- Ketika sebuah thread bangun dan mencoba memperoleh lock, sebuah bit disetel pada lock utama
- Di nsync, fungsi unlock bertanggung jawab membangunkan thread penunggu berikutnya
- Berkat bit ini, thread yang sedang melakukan unlock tidak perlu membangunkan penunggu kedua ketika sudah ada thread yang terbangun
- Kode sumber terkait ada di
cosmopolitan/third_party/nsync/mu.cdancosmopolitan/libc/intrin/pthread_mutex_lock.c
Layanan nyata dan kode verifikasi
- Sebagai demo live yang menggunakan Cosmo Mutex, server http://ipv4.games/ dapat dilihat
- Layanan ini berjalan di GCE VM 2-core dan sejauh ini telah bertahan dari DDoS botnet berskala hingga 49.131.669 IP
- Berkat nsync, query SQL dapat dipindahkan ke thread latar belakang dan struktur tempat thread saling mengirim pesan dapat digunakan
- Indikator status dapat dilihat di /statusz
- Kode benchmark mengukur wall time dengan
gettimeofday()dan mengukur user time serta system time dengangetrusage() - Pada akhirnya, kode memeriksa
g_chores == THREADS * ITERATIONSuntuk memverifikasi bahwa semua operasi increment telah dilakukan
Catatan saat melihat spin lock
- Dalam kondisi tanpa kontensi, perbedaan antarimplementasi Mutex kecil, dan spin lock beberapa baris bisa saja lebih baik
- Namun spin lock sebaiknya digunakan hanya ketika benar-benar tidak ada pilihan lain
- Spin lock berguna di tempat yang sulit memakai cara yang lebih kompleks karena batasan level sangat rendah, seperti kernel
- Spin lock juga dapat digunakan sebagai detail implementasi internal nsync lock
- Jika melihat performa lock hanya dari wall time, spin lock bisa tampak bagus, jadi waktu CPU juga harus diperiksa bersama dengan
getrusage()
1 komentar
Komentar Hacker News
Perbandingan dengan implementasi mutex baru memang selalu menarik, tetapi saya tidak suka metode benchmark ini. Ini tampak hampir seperti microbenchmark
Orang yang benar-benar menerapkan lock cepat biasanya memakai program multithread besar sebagai sarana uji kinerja utama. Dalam beban kerja kompleks dengan panjang critical section, jumlah thread yang saling berebut, dan tingkat kontensi yang bervariasi, faktor yang membuat mutex cepat atau lambat tampaknya berubah-ubah
Sebagai referensi, saya menulis fast lock untuk WebKit, menciptakan abstraksi ParkingLot untuk implementasi lock (juga dipakai di Rust dan Unreal Engine), dan dulu juga melakukan riset serta menulis makalah tentang fast lock untuk Java
Sebagai programmer audio real-time, biaya untuk mengambil mutex yang belum terkunci sudah lebih penting bagi saya. Di aplikasi kami, situasi ini sangat mendominasi. Demikian juga, saya ingin tahu biaya operasi
try-lockyang akan gagal, bukan saat N thread saling berebutKarena Cosmopolitan bersifat open source, saya bisa mengukurnya sendiri, tetapi tetap saja terasa kurang memuaskan
Sama seperti hash map, jarang ada satu hash map yang lebih baik untuk semua beban kerja yang mungkin
Mutex yang tidur selama waktu tetap saat gagal mengambil lock (misalnya 100µs) hampir selalu akan menggumpalkan pekerjaan sehingga mendekati perilaku ini dan bisa “menang” di benchmark. Tetapi pada aplikasi nyata, jika ada sedikit saja kontensi, mutex seperti itu mengerikan
Maksud saya bukan mutex ini buruk atau mutex pthread itu baik, melainkan microbenchmark tersebut tidak mengukur hal yang mampu memprediksi performa aplikasi nyata
Pada bagian “alasan Cosmopolitan Mutex bagus adalah karena memakai library nsync”, saya belum pernah mendengar nsync, tetapi Mike Burrows juga menulis implementasi mutex produksi milik Google: https://github.com/abseil/abseil-cpp/blob/master/absl/synchr...
Jadi saya penasaran kenapa implementasi mutex ini tidak masuk benchmark. Dan jika di macOS ia mendelegasikan ke
__ulock, sepertinya hal yang sama bisa dicapai dengan lebih sederhana hanya memakai fungsi anggotawait()dannotify_one()di library atomic milik libc++Dulu juga ada thread besar terkait perbaikan implementasi mutex Rust: https://github.com/rust-lang/rust/issues/93740#issuecomment-... yang menarik adalah detail cara kerja internal hampir semua implementasi mutex populer dibahas di sana
Mungkin benar, tetapi saya tidak bisa memastikannya sendiri. Dia adalah engineer yang sangat cerdas dan sangat berfokus pada efisiensi. Hanya saja kami tidak menjalankannya lama di satu server
Implementasi mutex Rust saat ini masuk awal tahun ini, dan di Linux mungkin tidak terlalu berbeda, tetapi di Windows dan Mac setahu saya itu pekerjaan baru
Meski begitu, penjelasan Mara tentang internal implementasi lain tetap menarik, hanya saja sebaiknya periksa apakah informasinya sudah usang untuk konteks Anda
https://awards.acm.org/award-recipients/burrows_9434147
Kalimat seperti “ini masih library C baru jadi masih ada bagian kasarnya, tapi peningkatannya terlalu cepat sampai-sampai mulai terasa seperti kelalaian profesional kalau tidak dipakai di production” terdengar cukup aneh. Saya sangat menghargai proyek Cosmopolitan, tetapi klaim superioritas yang terlalu dibesar-besarkan seperti ini biasanya merupakan tanda bahaya yang cukup buruk
Saya juga paham kalau bagi sebagian orang itu bisa terasa kasar. Dulu juga pernah muncul drama seperti itu di llamacpp
Dalam production, prioritas tertinggi bukanlah “menjadi jauh lebih baik dengan sangat cepat”, melainkan stabilitas, prediktabilitas, dan keandalan. Tentu saja performa juga penting. Kode yang lebih cepat bisa mengurangi infrastruktur sehingga lebih baik dari sisi biaya dan lingkungan. Tetapi cepat itu urutan terakhir
Misalnya, APE terasa seperti hack yang sangat mengesankan, tetapi kritik seperti “jadi sekarang bukan cuma tidak aman di satu platform, melainkan bisa sekaligus tidak aman di banyak platform?” juga mungkin saja.
Semakin lama berkecimpung di bidang teknologi, semakin terasa bahwa keuntungan timbal balik yang sempurna itu amat jarang, dan kebanyakan hal adalah trade-off yang selalu datang bersama sisi untung dan rugi
Ini memang agak menyimpang, tetapi sebagai pengembang game saya justru jadi menyukai mutex yang lambat untuk banyak pekerjaan debug di semua build pengembang. Misalnya punya nama/ID debug, melacak pemiliknya, melaporkan waktu yang dihabiskan untuk kontensi ke profiler, dan juga melaporkan perpindahan kepemilikan ke profiler.
Game cenderung menyusun konkurensi dengan cara yang berbeda, dan pola untuk menghindari lock juga sudah berkembang. Tetapi pola seperti itu sulit digunakan dan mengharuskan programmer mengubah strukturnya. Sebagian besar kode berawal dari “tempelkan lock di sini dulu lalu coba lewat milestone”.
Bahkan lock yang cepat pun bisa melambat secara tak terduga, dan kalau tadinya ada jaminan real-time, lock itu bisa merusaknya. Rata-ratanya mungkin cepat, tetapi tail latency tidak hilang. Saya tidak ingin jadi orang yang harus kembali melacak “kenapa game kita tersendat”, tetapi biasanya memang saya yang jadi orang itu.
Jadi saya lebih memilih lock yang lambat. Maksud saya lock yang terlihat besar dan merah di profiler. Kalau kelihatan sedang menghantam kita, ya refactor saja lalu hilangkan.
Saya tahu ini tuntutan yang sulit. Di production AAA, orang yang benar-benar bisa memakai profiler bisa dihitung dengan jari. Dari beberapa production yang pernah saya lihat, kondisinya selalu begitu.
Maaf jadi curhat, tetapi saya tetap berharap riset tentang primitif konkurensi cepat dan algoritme semacam ini terus berlanjut
Dalam game, kalau memungkinkan kita sama sekali tidak menginginkan kontensi lock, dan dalam banyak kasus kita bisa membuktikan bahwa mengambil lock itu tidak perlu. Misalnya, setiap frame dibagi menjadi beberapa tahap, dan akses mutable ke resource bersama tertentu hanya dibutuhkan pada tahap tertentu. Contohnya
update()sebelumrender()atau hot reload aset.Dengan memakai scoped thread dan aturan peminjaman Rust, kita bisa menyusun arsitektur sedemikian rupa sehingga mutex sama sekali tidak diperlukan, dan kita bisa yakin bahwa saat nanti perubahan kode membuatnya dibutuhkan, compiler akan mengeluarkan error yang tegas.
Kalau memungkinkan, selalu lebih baik menerima error kompilasi daripada spike di profiler
Di satu sisi, keluarga Cosmo/APE/redbean terlihat benar-benar mengesankan, dan komentar pada tulisan terkait juga umumnya positif, hampir tidak ada yang membantah konsepnya sendiri. Namun di sisi lain, saya hampir tidak pernah mendengar ada orang lain yang benar-benar memakainya
Tidak semua orang membagikan pekerjaan mereka secara besar-besaran, tetapi kalau sudah lewat beberapa tahun, rasanya saya setidaknya akan melihat beberapa tulisan retrospektif proyek. Semua penyebutan Cosmo/APE/redbean yang saya lihat berasal dari situs Justine
Jadi saya penasaran. Apakah ada jebakan tersembunyi? Apakah ini alat yang melakukan sesuatu yang buruk demi mendapatkan hasil? Apakah ini semacam lelucon atau trolling ala tom7 yang tidak saya pahami karena saya tidak cukup paham compiler atau runtime? Atau memang ini benar-benar alat brilian yang belum tersebar luas?
APE bekerja dengan trik cerdik yang sewaktu-waktu bisa diblokir, dan di OpenBSD itu memang benar-benar sudah diblokir
Kebanyakan orang yang membuat perangkat lunak lintas platform tidak menginginkan satu executable tunggal yang berjalan di semua platform, melainkan satu codebase tunggal yang bekerja dengan benar di setiap platform yang didukung
Dari sudut pandang itu, bahasa seperti Go terasa menyenangkan karena jika menghindari CGO, Anda bisa cross-compile ke semua target. Tetapi sulap agar bisa dieksekusi dengan tiga cara milik APE, meskipun sangat cerdas, tidak memberi keyakinan bahwa itu akan bekerja selamanya, dan bagi kebanyakan orang juga hampir tidak memberi manfaat praktis
Setiap platform punya persyaratan packaging dan penandatanganan masing-masing, jadi lebih baik compile terpisah untuk target tiap platform
Secara pribadi, cosmo dan ape memang terlihat sangat cerdas, tetapi kalau alat biasa sudah bekerja dengan baik, saya tidak butuh kecerdikan semacam ini dalam pekerjaan
Misalnya jika Anda sudah bisa cross-compile proyek ke sistem operasi dan platform lain, atau sudah punya infrastruktur build untuk itu, tidak ada alasan untuk mencari solusi yang membuat satu binary tunggal yang berjalan di mana-mana
Selain itu, APE memakai hack cerdik agar bisa berjalan di beberapa sistem operasi. Bagaimana kalau suatu saat hack itu rusak ketika format executable berevolusi? Bagaimana kalau tidak ada siapa pun yang punya waktu untuk memperbaiki APE agar mengikuti perubahan itu?
Sebaliknya, alat-alat yang membosankan seperti gcc, clang, go, rust akan terus diperbarui dan tetap bekerja meski sistem operasi terus berubah dan berevolusi. Jadi saya tetap berada di sisi yang membosankan. Alasan saya tidak memikirkan hal yang cerdas adalah karena yang membosankan bagi saya ya sudah bekerja dengan baik
llamafile dari Mozilla memakai ini. Bobot model dan executable digabung menjadi satu agar bisa dijalankan di mana saja pada platform cosmo/ape, dan juga menyalakan server HTTP redbean untuk interaksi
Ia juga bisa dijalankan tanpa bobot yang digabungkan dan membaca bobot dari filesystem. Ini mungkin cara termudah untuk membuat LLM lokal benar-benar bisa “unduh lalu langsung jalan”
Cosmopolitan selalu terasa seperti celah teknis yang menarik untuk bahan tulisan blog. Jenis hal yang hampir pasti bisa masuk halaman depan tempat seperti HN hanya dengan kecerdikan dan obsesi terhadap setup-nya
Tetapi untuk dipakai sebagai teknologi dasar seperti
libc, ini tampak terutama berguna untuk mainan yang menarik atau proyek pribadi kecilDalam konteks itu, ketika ini diajukan sebagai alternatif serius untuk hal seperti
glibc,musl,msvcrt, rasanya agak aneh. Ini hack yang sangat lucu, tetapi kalau saya menemukannya dalam sesuatu yang saya andalkan secara serius, saya mungkin akan cukup terkejutMozilla punya proyek Llamafile berbasis Cosmopolitan libc: https://github.com/Mozilla-Ocho/llamafile
Di Hugging Face juga rutin diunggah model-model populer yang dikemas ulang dalam format itu: https://huggingface.co/models?search=llamafile
Namun apakah itu punya kegunaan praktis lebih dari sekadar mencoba model kecil dengan cepat adalah persoalan lain
Kalau memang sebagus itu, saya jadi penasaran kenapa tidak semua library C mengadopsi trik yang sama
Dugaan saya, trik-trik itu mungkin hanya selalu lebih cepat pada arsitektur tertentu, model CPU tertentu, beban kerja tertentu, atau pola akses tertentu. Jika diuji dengan benar pada berbagai beban kerja di semua perangkat keras yang didukung, mungkin keunggulan yang sama tidak muncul
Atau bisa juga semantik API pthread yang ingin diimplementasikan Cosmopolitan sedikit berbeda, dan implementasi ini mungkin tidak sepenuhnya patuh ketat pada spesifikasi
Sulit membayangkan para penulis libc tidak mengikuti riset terbaru tentang primitif sistem operasi
mallocdi glibc lumayan bisa dipakai, tetapi dalam kecepatan keseluruhan dan skalabilitas, ia mudah kalah dari alternatif yang lebih modern. Fragmentasinya parah dan memburuk seiring waktu, serta ada banyak parameter tuning sepertiMALLOC_ARENA_MAXyang sangat memengaruhi beban kerja nyata.mallocmusl benar-benar buruk di semua level dari sisi performa. Menggunakan allocator musl pada program multithread bisa merusak performa dengan sangat parah sampai nyaris terasa lalaiMusl juga tidak punya routine perbandingan string yang dioptimalkan dengan SIMD. Anda akan terkejut kalau tahu berapa banyak siklus CPU yang dihabiskan untuk pekerjaan seperti ini pada program yang tidak sepele; ini jelas terlihat dalam profil nyata, dan memperbaikinya akan membuat hampir semua program menjadi lebih baik secara umum. Routine optimalisasi glibc bagus, tetapi tetap tampak masih bisa dibuat lebih cepat
Hal-hal seperti ini bukanlah “optimalisasi yang hanya khusus untuk satu arsitektur dan tidak bisa digeneralisasi”. Khususnya dua area ini adalah area yang sudah banyak dieksplorasi dan dipahami, yang hampir pada semua beban kerja dapat memangkas waktu wall-clock 2–5x dan juga sangat meningkatkan pemanfaatan working set jangka panjang. Lalu kenapa tidak diadopsi? Seperti biasa, mungkin karena ada hal lain yang harus dikerjakan, atau karena ada prioritas yang saling bertentangan seperti pada musl, yang lebih mengutamakan kesederhanaan daripada performa puncak
Ini bukan menyalahkan proyek-proyek tersebut. Tidak ada yang berkata, “program saya sengaja dirancang agar sangat lambat dan tidak bisa melakukan apa pun dengan benar, dan saya bangga akan itu.” Hanya saja, gagasan bahwa para penggarap proyek itu merancangnya dengan memilih frontier Pareto yang sempurna sama sekali tidak realistis, dan tidak mencerminkan cara kebanyakan proyek benar-benar berjalan
Untuk mengubah sesuatu di glibc atau padanannya di dunia C++, butuh waktu selamanya
Ada berbagai jenis primitif sinkronisasi, dan pthreads hanya mendukung sebagian di antaranya. Jika membatasi diri pada itu, biasanya artinya menukar performa demi portabilitas
Saya tidak tahu soal maintainer libc, tetapi sebagai orang yang memelihara beberapa hal, saya tidak berusaha mengimplementasikan riset terbaru. Saya berusaha menjaga stabilitas dan memastikan performanya masih bisa diterima. Implementasi riset ada di luar anggaran “maintenance” saya
Seorang pria dan seorang ahli statistik sedang berjalan di jalan lalu melihat uang kertas 50 euro. Ahli statistik itu terus berjalan, dan si pria berhenti lalu berkata, “Lihat, ada uang di lantai.” Ahli statistik menjawab, “Itu pasti palsu. Kalau asli, pasti sudah dipungut seseorang,” lalu terus berjalan. Pria yang satunya lagi mengambil uang itu
Thread dan mutex adalah hal yang paling membuat segala sesuatu menjadi rumit dalam ilmu komputer. Implementasi baru selalu saya pandang dengan skeptis sampai dipakai dalam skala besar selama bertahun-tahun
Bug dalam mekanisme threading seperti ini sering lolos bahkan dari peninjauan paling ketat sekalipun. Saat Java muncul pada pertengahan 90-an, berbagai bug thread dan mutex di Solaris pun terungkap
Yang dibutuhkan bukan implementasi mutex tercepat, melainkan implementasi yang bisa dipercaya
Kode ini tidak membenchmark performa lock mutex, melainkan kontensi mutex. Kalau Anda memakai lock seperti ini, kodenya perlu dievaluasi ulang
Setiap kali tiap thread menambah
g_chores, ia mengunci lalu membuka mutex. Ini menimbulkan overhead akuisisi dan pelepasan mutex yang sering, dan itu diulang 100.000 kali per threadOverhead ini menutupi perbedaan performa nyata antar mekanisme lock. Karena benchmark-nya didominasi kontensi lock, bukan pekerjaan nyata. Benchmark seperti ini tidak berguna
Saya penggemar Justine dan pekerjaannya, tetapi ini mungkin salah satu kasus uji benchmark mutex yang paling tidak menarik. Situasi ketika banyak thread terus-menerus menghantam mutex yang sama justru sesuatu yang sejak awal sebaiknya dihindari
Jadi saya rasa tidak terlalu menarik mutex implementasi mana yang paling baik menangani kasus ini
Ada satu hal penting yang tadi terlewat: lock yang buruk performanya saat kontensi juga bisa menimbulkan efek sistemik yang sangat negatif, seperti menciptakan hotspot di jaringan memori, dan itu juga akan terlihat di sini
Saya bisa memikirkan beberapa kasus ketika banyak thread memang berkumpul pada mutex yang sama. Contoh sederhananya adalah pekerjaan mengisi struktur data seperti list atau dictionary secara bersamaan
Itu memang bisa dilakukan dengan message passing, tetapi bisa memakai lebih banyak memori dan mungkin lebih lambat daripada menunggu untuk menulis ke lokasi bersama
Produksi bukan soal kecepatan, efisiensi, atau sekadar “hack cerdas” yang jelas-jelas pintar
Jika saya harus mengorbankan 50% efisiensi demi jaminan bahwa saya tidak akan dipanggil untuk memperbaiki sistem yang rusak pada Minggu pukul 3 pagi, saya akan memilih itu setiap saat
Produksi adalah soal keandalan, dan menulis kode yang andal itu 10 kali lebih sulit daripada menulis kode yang “cepat”