Mengapa tim di LMAX menggunakan Java dan merancang arsitektur untuk menghindari GC dengan cara apa pun?

24

Mengapa tim di LMAX merancang LMAX Disruptor di Java tetapi semua poin desain mereka untuk meminimalkan penggunaan GC? Jika seseorang tidak ingin menjalankan GC maka mengapa menggunakan bahasa sampah yang dikumpulkan?

Optimalisasi mereka, tingkat pengetahuan perangkat keras dan pemikiran yang mereka buat sangat mengagumkan tetapi mengapa Java?

Saya tidak menentang Java atau apa pun, tapi mengapa bahasa GC? Mengapa tidak menggunakan sesuatu seperti D atau bahasa lain tanpa GC tetapi memungkinkan kode yang efisien? Apakah itu tim yang paling akrab dengan Jawa atau apakah Jawa memiliki beberapa keunggulan unik yang tidak saya lihat?

Katakanlah mereka mengembangkannya menggunakan D dengan manajemen memori manual, apa bedanya? Mereka harus berpikir tingkat rendah (yang sudah ada), tetapi mereka dapat memeras kinerja terbaik dari sistem karena itu asli.


sumber
6
Saya tahu sedikit tentang proyek ini, tetapi tampaknya ini adalah semacam kerangka kerja yang dapat dibangun oleh orang lain. Dan jika Anda berhasil menulis itu di Jawa (dan memungkinkan orang lain untuk kode di Jawa dan menuai manfaatnya), maka Anda akan memiliki "basis pelanggan" yang JAUH lebih besar daripada jika Anda akan menulisnya di D.
Joachim Sauer
6
@ kadaj: tidak masalah jika konsumennya publik atau internal: jika Anda membuatnya dapat diakses dalam bahasa yang dikenal luas, itu akan lebih bermanfaat, bahkan untuk pengembangan internal. Jika Anda memulai argumen (hipotesis) Anda dengan: "Asumsikan semua orang tahu D dan juga mereka tahu Java, ...", maka Anda mungkin kehilangan sesuatu.
Joachim Sauer
6
Beberapa orang suka menggunakan palu untuk semua jenis masalah. Punya tepi kasar yang Anda inginkan, bash dengan palu hingga halus. Punya sekrup yang perlu Anda bawa masuk, bash dengan palu sampai masuk. Punya ornamen halus yang Anda butuhkan untuk diampelas, bash dengan palu, dan salahkan ornamen untuk "mengisap". C atau C ++ akan menjadi pilihan yang lebih baik daripada D, jika hanya untuk basis pengetahuan yang ada. Tidak yakin mengapa Anda menyebut D sebagai contoh TBH.
gbjbaanb
2
@ gbjbaanb saya sebutkan D karena menyediakan pengumpulan sampah (dalam kasus di mana abstraksi tingkat tinggi diperlukan dan mengutak-atik memori terlalu sulit untuk otak) tetapi juga memungkinkan manajemen memori manual dengan C gaya malloc dan gratis. D adalah semacam Objective-C dengan ARC (tidak ada GC nyata) tetapi lebih baik dari itu. Tapi ya, C / C ++ akan sesuai dengan tagihan.
4
@ kadaj Saya melihat Anda telah mendapatkan beberapa kritik di sini karena membawa D tetapi saya ingin mengatakan saya kecewa dengan nada yang digunakan orang lain dan menjelaskan mengapa saya pikir D adalah pusat pertanyaan yang ada. Sementara D memang tidak banyak digunakan, D menyediakan beberapa konstruksi tingkat tinggi yang mungkin saya harapkan untuk ditemukan di katakanlah Java atau C # tetapi tidak dalam (setidaknya gaya lama) C ++. Itu masih menyediakan untuk pencampuran dikelola dan tidak dikelola - yang merupakan satu-satunya bahasa yang saya tahu untuk melakukan itu! Jadi D bukan hanya pilihan hewan peliharaan, tetapi lebih tepatnya yang memiliki tujuan yang bertepatan dengan pertanyaan awal seputar GC.
J Trana

Jawaban:

20

Karena ada perbedaan besar antara mengoptimalkan kinerja dan mematikan sepenuhnya keselamatan

Dengan mengurangi jumlah GC, kerangka kerja mereka lebih responsif dan dapat berjalan (mungkin) lebih cepat. Sekarang, mengoptimalkan pengumpul sampah tidak berarti mereka tidak pernah melakukan pengumpulan sampah. Itu hanya berarti mereka melakukannya lebih jarang, dan ketika mereka melakukannya, itu berjalan sangat cepat. Jenis optimasi tersebut meliputi:

  1. Meminimalkan jumlah objek yang pindah ke ruang selamat (yaitu yang bertahan setidaknya satu pengumpulan sampah) dengan menggunakan benda-benda kecil yang dibuang. Objek yang dipindahkan ke ruang selamat lebih sulit untuk dikumpulkan dan pengumpulan sampah di sini kadang-kadang menyiratkan seluruh JVM.
  2. Jangan mengalokasikan terlalu banyak objek untuk memulai. Ini bisa menjadi bumerang jika Anda tidak hati-hati, karena objek generasi muda sangat murah untuk dialokasikan dan dikumpulkan.
  3. Pastikan bahwa objek baru menunjuk ke yang lama (dan bukan sebaliknya) sehingga objek muda mudah dikumpulkan, karena tidak ada referensi kepada mereka yang akan menyebabkan mereka disimpan

Ketika Anda mengabaikan kinerja, Anda biasanya mencari beberapa "hot spot" yang sangat spesifik sambil mengabaikan kode yang tidak sering berjalan. Jika Anda melakukannya di Jawa, Anda dapat membiarkan pengumpul sampah tetap merawat sudut-sudut gelap itu (karena itu tidak akan membuat banyak perbedaan) sambil mengoptimalkan dengan sangat hati-hati untuk area yang berjalan dalam loop ketat. Jadi Anda dapat memilih di mana Anda mengoptimalkan dan di mana Anda tidak, dan dengan demikian Anda dapat memfokuskan upaya Anda di tempat yang penting.


Sekarang, jika Anda mematikan pengumpulan sampah sepenuhnya, maka Anda tidak dapat memilih. Anda harus membuang setiap objek secara manual . Metode itu dipanggil paling banyak sekali sehari? Di Jawa, Anda dapat membiarkannya, karena dampak kinerjanya dapat diabaikan (mungkin OK untuk membiarkan GC penuh terjadi setiap bulan). Di C ++, Anda masih membocorkan sumber daya, jadi Anda harus berhati-hati bahkan dari metode yang tidak jelas itu. Jadi, Anda harus membayar harga untuk manajemen sumber daya di setiap bagian aplikasi Anda, sementara di Jawa Anda dapat fokus.


Tapi itu semakin buruk.

Bagaimana jika Anda memiliki bug, katakanlah di sudut gelap aplikasi Anda yang hanya diakses pada hari Senin di bulan purnama? Jawa memiliki jaminan keamanan yang kuat. Ada sedikit atau tidak ada "perilaku tidak terdefinisi". Jika Anda menggunakan sesuatu yang salah, Pengecualian dilempar, program Anda berhenti, dan tidak ada kerusakan data terjadi. Jadi Anda cukup yakin bahwa tidak ada yang salah dapat terjadi tanpa Anda sadari.

Tetapi dalam sesuatu seperti D, Anda dapat memiliki akses pointer buruk, atau buffer overflow, dan Anda dapat merusak memori Anda, tetapi program Anda tidak akan tahu (Anda mematikan keselamatan, ingat?) Dan akan terus berjalan dengan salahnya data, dan melakukan beberapa hal yang cukup jahat dan merusak data Anda, dan Anda tidak tahu, dan semakin banyak korupsi terjadi, data Anda semakin salah, dan kemudian tiba-tiba rusak, dan itu dalam aplikasi yang sangat penting, dan beberapa kesalahan terjadi dalam perhitungan roket, sehingga tidak berfungsi, dan roket meledak, dan seseorang mati, dan perusahaan Anda ada di halaman depan setiap surat kabar dan bos Anda mengarahkan jarinya ke Anda mengatakan "Kamu adalah insinyur yang menyarankan agar kami menggunakan D untuk mengoptimalkan kinerja, mengapa Anda tidak memikirkan keselamatan?". Dan itu salahmu. Kamu membunuh orang-orang itu dengan upaya bodohmu dalam kinerja.


OKE, OKE, sebagian besar waktu itu jauh kurang dramatis dari itu. Tetapi bahkan aplikasi penting bisnis atau hanya aplikasi GPS atau, katakanlah, situs web layanan kesehatan pemerintah dapat menghasilkan konsekuensi yang cukup negatif jika Anda memiliki bug. Menggunakan bahasa yang mencegah mereka sepenuhnya atau gagal-cepat ketika mereka terjadi biasanya adalah ide yang sangat bagus.

Ada biaya untuk mematikan pengaman. Menjadi asli tidak selalu masuk akal. Kadang jauh lebih mudah dan lebih aman untuk hanya mengoptimalkan sedikit bahasa yang aman untuk masuk semua untuk bahasa di mana Anda dapat menembak diri sendiri dalam waktu besar. Kebenaran dan keamanan dalam banyak kasus mengalahkan beberapa nano detik yang akan Anda hilangkan dengan menghilangkan GC sepenuhnya. Disruptor dapat digunakan dalam situasi itu, jadi saya pikir LMAX-Exchange membuat panggilan yang tepat.

Tapi bagaimana dengan D khususnya? Anda memiliki GC jika Anda ingin sudut-sudut gelap, dan subset SafeD (yang saya tidak tahu sebelum mengedit) menghapus perilaku yang tidak terdefinisi (jika Anda ingat untuk menggunakannya!).

Nah dalam hal ini pertanyaan sederhana tentang kedewasaan. Ekosistem Jawa penuh dengan alat yang ditulis dengan baik dan perpustakaan yang matang (lebih baik untuk pengembangan). Lebih banyak pengembang yang tahu Java daripada D (lebih baik untuk pemeliharaan). Memilih bahasa baru dan tidak terlalu populer untuk sesuatu yang sama pentingnya dengan aplikasi finansial bukanlah ide yang bagus. Dengan bahasa yang kurang dikenal, jika Anda memiliki masalah, sedikit yang dapat membantu Anda, dan perpustakaan yang Anda temukan cenderung memiliki lebih banyak bug karena mereka terpapar pada lebih sedikit orang.

Jadi poin terakhir saya masih berlaku: jika Anda ingin menghindari masalah dengan konsekuensi yang mengerikan, tetaplah dengan pilihan yang aman. Pada titik ini dalam kehidupan D, pelanggannya adalah perusahaan baru kecil yang siap mengambil risiko gila. Jika masalah dapat menelan biaya jutaan, Anda lebih baik tinggal lebih jauh dalam kurva lonceng inovasi .

Laurent Bourgault-Roy
sumber
2
Posting asli secara khusus memanggil D. Sebenarnya ada perbedaan yang cukup besar antara C ++ dan D sehubungan dengan granularity pilihan. Bahkan jika Anda memilih untuk dikelola penuh di subset SafeD, saya pikir Anda mendapatkan sedikit lebih banyak kontrol atas aspek pengumpulan dan pemilihan waktu tertentu (aktifkan / nonaktifkan, kumpulkan, perkecil). Lihatlah strategi Digital Mars untuk manajemen memori!
J Trana
2
lmax dengan sengaja menaungi beberapa keamanan yang disediakan Java
James
Ini akan menjadi jawaban yang bagus, kecuali Java tidak berlisensi untuk perangkat lunak misi kritis. Jika Anda memiliki reaktor nuklir, itu akan ditulis dalam C ++ dan bukan Java, yang agak membuang seluruh aspek "keamanan".
gbjbaanb
@ gbjbaanb, [rujukan?] Standar / pedoman reliabilitas yang saya lihat merekomendasikan pertama menghindari C / C ++ yang mendukung bahasa lain; dan jika masuk ke dalamnya, maka gunakan versi bahasa yang sangat terbatas (MISRA, dll). Dan begitu Anda menerima batasan, saya tidak mengerti mengapa Anda tidak dapat melakukan hal yang sama dengan bahasa lain. Jika Anda berpikir tentang penyebutan Java Licence tentang "bukan untuk fasilitas nuklir" di bagian PEMBATASAN, sepertinya itu berubah beberapa waktu lalu dan sekarang malah mengatakan sesuatu yang mirip "hati-hati, bukan tanggung jawab kami". Namun, saya menganggap (...)
hmijail
(...) Kalimat aslinya sama seperti lisensi gcc dan dentang: tidak ada jaminan untuk tujuan tertentu. Jadi Anda tidak akan menggunakannya untuk sesuatu yang membutuhkan keandalan, dan sebaliknya Anda harus menggunakan beberapa kompiler bersertifikat, jika tidak pergi ke beberapa bahasa tertentu untuk pekerjaan itu (Ada?).
hmijail
4

Tampaknya alasan itu ditulis di Jawa adalah bahwa mereka memiliki keahlian Java di rumah dan mungkin ditulis (meskipun masih dalam pengembangan aktif) sebelum C ++ bertindak bersama dengan C ++ 0x / 11.

Kode mereka benar-benar hanya Java dengan nama, mereka menggunakan sun.misc.Unsafe agak seperti yang mengalahkan titik Jawa dan keamanan yang seharusnya diberikan. Saya telah menulis port C ++ dari Disruptor dan mengungguli kode Java yang mereka kirimkan (saya tidak menghabiskan banyak waktu menyetel JVM).

Karena itu, prinsip-prinsip yang diikuti pengganggu tidak spesifik bahasa, mis. Jangan berharap kode C ++ latensi rendah yang dialokasikan atau dibebaskan dari heap.

James
sumber
Bisakah Anda menunjukkan implementasi Anda? Saya melihat beberapa implementasi seperti itu daripada mengklaim kinerja yang lebih tinggi, tetapi keduanya menipu dengan penyederhanaan: misalnya, pekerja keras 1 produsen + 1 konsumen alih-alih menjadi multi-produsen / konsumen yang mampu seperti Disruptor asli. Penulis Disruptor sendiri menyebutkan dalam utas Google Groups bahwa kinerja dapat ditingkatkan dengan parameter bawaan dalam versi Java.
hmijail
4

Pertanyaan ini menyatakan premis yang salah sebagai fakta, lalu membuat argumen tentang premis yang salah itu.

Mari gali ini .. "semua titik desain mereka untuk meminimalkan penggunaan GC" - tidak benar. Inovasi dalam pengganggu tidak ada hubungannya dengan GC. Pengacau berkinerja karena desainnya dengan cerdik mempertimbangkan bagaimana komputer modern bekerja - sesuatu yang jauh lebih jarang daripada yang diharapkan. Lihat ceramah Cliff Click di http://www.azulsystems.com/events/javaone_2009/session/2009_J1_HardwareCrashCourse.pdf untuk diskusi.

Sudah diketahui bahwa LMax adalah pelanggan Azul. Saya tahu secara langsung bahwa dengan Azul GC bukan merupakan masalah - bahkan dengan tumpukan 175GB.

peterbooth
sumber
Ada sebutir kebenaran untuk ini. Mereka me-restart VM setiap malam untuk menghindari koleksi besar. Itulah yang ditulis Martin Fowler, dan dia tidak bodoh: "Seperti sistem lainnya, para pengganggu terpental semalaman. Bouncing ini terutama dilakukan untuk menghapus memori sehingga ada sedikit peluang terjadinya pengumpulan sampah yang mahal selama perdagangan." martinfowler.com/articles/lmax.html
JimmyJames
2
Tidak terlalu. Kami biasa memicu GC manual setiap malam dalam celah perdagangan 5 menit, dan menyesuaikannya sehingga menjadi satu-satunya GC utama dalam sehari. Itu menjadi berlebihan dengan Azul Zing. (Sumber: Saya bekerja di LMAX sampai baru-baru ini)
Tom Johnson
@ TomJohnson Cinta mendapatkan sendok dalam. Apakah Anda mengatakan bahwa deskripsi Martin Fowler salah? Apakah mungkin solusinya berkembang dari waktu ke waktu?
JimmyJames
2
Saya mengatakan dia tidak benar pada beberapa detail kecil. Kami tidak pernah memantulkan sistem kami setiap hari, tetapi kami memang melakukan pembersihan akhir hari.
Tom Johnson
3

Mereka harus berpikir level rendah

Di atas membuat separuh dari jawaban yang Anda cari. Anda dapat menemukan setengah lainnya untuk melengkapi alasannya tidak lebih jauh dari pada di blog LMAX :

Meskipun sangat efisien, dapat menyebabkan sejumlah kesalahan karena sangat mudah untuk mengacaukan ...

Seperti yang diakui oleh pengembang LMAX, kode seperti itu mungkin cukup sulit untuk dikembangkan, dipahami, dan didebug - bahkan di Jawa. Menuju level yang lebih rendah dari tempat mereka sekarang hanya akan memperburuk masalah ini, seperti yang ditunjukkan dalam artikel Wikipedia tentang bahasa pemrograman tingkat rendah :

Program yang ditulis dalam bahasa tingkat rendah dapat dibuat untuk berjalan sangat cepat, dan dengan jejak memori yang sangat kecil; program setara dalam bahasa tingkat tinggi akan lebih berat. Bahasa tingkat rendah itu sederhana, tetapi dianggap sulit untuk digunakan, karena banyak detail teknis yang harus diingat .

Sebagai perbandingan, bahasa pemrograman tingkat tinggi mengisolasi semantik pelaksanaan arsitektur komputer dari spesifikasi program, yang menyederhanakan pengembangan ...

agas
sumber
3

Jika Anda menggunakan Java sebagai bahasa sintaks dan menghindari pustaka JDK, itu bisa secepat bahasa non-GC yang dikompilasi. GC tidak cocok untuk sistem waktu nyata, tetapi dimungkinkan untuk mengembangkan sistem di Jawa yang tidak meninggalkan sampah. Akibatnya GC tidak pernah memicu.

Kami percaya bahwa bahasa dan platform Java memiliki banyak keunggulan dibandingkan C / C ++ dan kami telah mengembangkan dan membuat tolok ukur beberapa komponen Java dengan latensi rendah untuk membuktikannya. Kami berbicara tentang teknik untuk melakukannya dalam artikel ini: Pengembangan Java tanpa GC .

rdalmeida
sumber
2
Ada pemulung yang cocok untuk sistem waktu nyata. Kolektor default JVM mungkin tidak, tetapi itu tidak berarti GC secara umum tidak cocok untuk waktu nyata. Tapi polos malloc/freejuga tidak cocok untuk waktu nyata karena waktu alokasi tidak dibatasi karena fragmentasi.
Doval
1
Kami menganjurkan penggunaan kolam objek cepat untuk semuanya sehingga tidak ada alokasi yang terjadi setelah pemanasan.
rdalmeida
2

LMAX adalah Perpustakaan Perpesanan Antar-Thread Berkinerja Tinggi.

Agar bermanfaat, orang lain harus menulis kode untuk mendapatkan setiap utas untuk melakukan pekerjaan yang bermanfaat. Mengingat bahwa kode tersebut kemungkinan besar berada di Java atau C # dan kemudian ada sangat sedikit pilihan bahasa yang berinteraksi dengan mereka.

Menggunakan C atau C ++ bukanlah pilihan yang baik kecuali jika Anda ingin membatasi pengguna Anda untuk satu OS, karena tidak ada model threading yang ditentukan di dalamnya.

Java adalah standar untuk banyak pengembangan perangkat lunak saat ini, jadi kecuali Anda memiliki alasan yang baik, Java cenderung menjadi pilihan terbaik. (Ketika di Roma lakukan sebagai orang Romawi ...)

Menulis perangkat lunak Kinerja Tinggi di Jawa (atau C #) sering dilakukan untuk membuktikan suatu hal ...

Ian
sumber
1
Standar C ++ 11 yang baru mendukung multithreading ...
Casey
@Casey, dan berapa banyak kompiler C ++ dunia nyata yang menggunakannya? Dan berapa biaya kompiler ini. Mungkin dalam 20 tahun ini akan berguna, sampai saat itu Anda tidak dapat bergantung padanya.
Ian
Disruptor menggunakan sun.misc.Unsafe sedikit yang menunjukkan bahwa Anda tidak dapat benar-benar menulis kode latensi rendah di Jawa tanpa mencelupkan kaki Anda ke tanah C
James
3
Gcc mendukung utas C ++ dan gratis
James
@Ian: 2 tahun kemudian dan semua kompiler yang digunakan umum mendukungnya;). Bahkan yang gratis.
Rutix