Secara teknis, mengapa proses di Erlang lebih efisien daripada thread OS?

170

Karakteristik Erlang

Dari Erlang Programming (2009):

Konkurensi erlang cepat dan terukur. Prosesnya ringan karena mesin virtual Erlang tidak membuat utas OS untuk setiap proses yang dibuat. Mereka dibuat, dijadwalkan, dan ditangani dalam VM, independen dari sistem operasi yang mendasarinya. Akibatnya, waktu pembuatan proses adalah urutan mikrodetik dan independen dari jumlah proses yang ada secara bersamaan. Bandingkan ini dengan Java dan C #, di mana untuk setiap proses thread OS yang mendasarinya dibuat: Anda akan mendapatkan beberapa perbandingan yang sangat kompetitif, dengan Erlang mengungguli kedua bahasa.

Dari pemrograman berorientasi Concurrency di Erlang (pdf) (slide) (2003):

Kami mengamati bahwa waktu yang diperlukan untuk membuat proses Erlang adalah konstan 1μs hingga 2.500 proses; setelah itu meningkat menjadi sekitar 3μs hingga 30.000 proses. Kinerja Java dan C # ditampilkan di bagian atas gambar. Untuk sejumlah kecil proses, dibutuhkan sekitar 300 μs untuk membuat proses. Membuat lebih dari dua ribu proses adalah hal yang mustahil.

Kami melihat bahwa hingga 30.000 proses waktu untuk mengirim pesan antara dua proses Erlang adalah sekitar 0,8 μs. Untuk C # dibutuhkan sekitar 50μs per pesan, hingga jumlah maksimum proses (yaitu sekitar 1800 proses). Java bahkan lebih buruk, untuk hingga 100 proses dibutuhkan sekitar 50 μs per pesan setelah itu meningkat pesat menjadi 10 ms per pesan ketika ada sekitar 1000 proses Java.

Pikiran saya

Saya tidak sepenuhnya mengerti secara teknis mengapa proses Erlang jauh lebih efisien dalam memunculkan proses baru dan memiliki jejak memori yang jauh lebih kecil per proses. Baik OS dan Erlang VM harus melakukan penjadwalan, konteks switch, dan melacak nilai-nilai dalam register dan seterusnya ...

Hanya mengapa thread OS tidak diimplementasikan dengan cara yang sama dengan proses di Erlang? Apakah mereka harus mendukung sesuatu yang lebih? Dan mengapa mereka membutuhkan jejak memori yang lebih besar? Dan mengapa mereka memiliki pemijahan dan komunikasi yang lebih lambat?

Secara teknis, mengapa proses di Erlang lebih efisien daripada utas OS ketika menyangkut pemijahan dan komunikasi? Dan mengapa thread di OS tidak dapat diimplementasikan dan dikelola dengan cara yang efisien? Dan mengapa utas OS memiliki jejak memori yang lebih besar, ditambah pemijahan dan komunikasi yang lebih lambat?

Lebih banyak membaca

Jonas
sumber
1
Sebelum mencoba memahami alasan mengapa hipotesis itu benar, Anda perlu menentukan apakah hipotesis itu benar - misalnya, didukung oleh bukti. Apakah Anda memiliki referensi untuk setiap seperti-untuk-seperti perbandingan menunjukkan bahwa proses Erlang sebenarnya adalah lebih efisien daripada (katakanlah) thread Java pada up-to-date JVM? Atau aplikasi C yang menggunakan proses OS dan dukungan utas secara langsung? (Yang terakhir tampaknya sangat, sangat tidak mungkin bagi saya. Yang pertama hanya agak mungkin.) Maksud saya, dengan lingkungan yang cukup terbatas (poin Francisco), itu mungkin benar, tetapi saya ingin melihat jumlahnya.
TJ Crowder
1
@ Donal: Seperti halnya banyak pernyataan absolut lainnya. :-)
TJ Crowder
1
@Jonas: Terima kasih, tapi saya mendapatkan tanggal (1998-11-02) dan versi JVM (1.1.6) dan berhenti. Sun's JVM telah meningkat sedikit dalam 11,5 tahun terakhir (dan mungkin juga penerjemah Erlang), terutama di bidang threading. (Untuk lebih jelasnya, saya tidak mengatakan bahwa hipotesis itu tidak benar [dan Francisco dan Donal telah menunjukkan mengapa Erland mungkin dapat melakukan sesuatu di sana]; Saya mengatakan itu tidak boleh diambil pada nilai nominal tanpa diperiksa.)
TJ Crowder
1
@Jonas: "... tapi saya kira Anda bisa melakukannya di Erlang ..." Itu bagian "tebak", kawan. :-) Anda menduga proses pengalihan Erlang melampaui ribuan. Anda menduga itu lebih baik daripada utas Java atau OS. Menebak dan pengembang perangkat lunak bukanlah kombinasi yang hebat. :-) Tapi saya pikir saya sudah menyampaikan maksud saya.
TJ Crowder
17
@TJ Crowder: Instal erlang dan jalankan erl +P 1000100 +hms 100dan ketikkan {_, PIDs} = timer:tc(lists,map,[fun(_)->spawn(fun()->receive stop -> ok end end) end, lists:seq(1,1000000)]).dan kemudian tunggu sekitar tiga menit untuk hasil. Itu sangat sederhana. Dibutuhkan 140us per proses dan 1GB seluruh RAM pada laptop saya. Tapi itu bentuk langsung shell, itu harus lebih baik dari kode yang dikompilasi.
Hynek -Pichi- Vychodil

Jawaban:

113

Ada beberapa faktor yang berkontribusi:

  1. Proses Erlang bukan proses OS. Mereka diimplementasikan oleh Erlang VM menggunakan model threading kooperatif ringan (preemptive di tingkat Erlang, tetapi di bawah kendali runtime terjadwal kooperatif). Ini berarti bahwa jauh lebih murah untuk beralih konteks, karena mereka hanya beralih pada titik-titik yang diketahui dan dikendalikan dan karenanya tidak perlu menyimpan seluruh keadaan CPU (normal, register SSE dan FPU, pemetaan ruang alamat, dll.).
  2. Proses Erlang menggunakan tumpukan yang dialokasikan secara dinamis, yang mulai sangat kecil dan tumbuh seperlunya. Hal ini memungkinkan pemunculan ribuan - bahkan jutaan - proses Erlang tanpa menyedot semua RAM yang tersedia.
  3. Erlang digunakan untuk single-threaded, artinya tidak ada persyaratan untuk memastikan keamanan benang di antara proses. Sekarang mendukung SMP, tetapi interaksi antara proses Erlang pada penjadwal / inti yang sama masih sangat ringan (ada antrian run terpisah per core).
Marcelo Cantos
sumber
6
Ke poin ke-2 Anda: Dan jika prosesnya belum berjalan, tidak ada alasan untuk mengalokasikan stack untuknya. Selain itu: Beberapa trik dapat dimainkan dengan mengutak-atik GC dari suatu proses sehingga tidak pernah mengumpulkan memori. Tapi itu sudah maju dan agak berbahaya :)
I GIVE CRAP JAWABAN
3
Ke poin ke-3 Anda: Erlang memberlakukan data yang tidak dapat diubah, jadi memperkenalkan SMP seharusnya tidak memengaruhi keamanan utas.
nilskp
@ nilskp, itu benar, erlang juga merupakan bahasa pemrograman fungsional. Jadi tidak ada data "variabel". Ini mengarah pada keamanan thread.
liuyang1
6
@nilskp: (RE: Anda mengomentari poin 3 ...) Meskipun bahasa itu sendiri memiliki sistem tipe yang tidak dapat diubah, implementasi yang mendasarinya - pengiriman pesan, penjadwal, dll. - adalah cerita yang berbeda sama sekali. Dukungan SMP yang benar dan efisien tidak terjadi begitu saja dengan jentikan sakelar.
Marcelo Cantos
@rvirding: Terima kasih atas addendum klarifikasi. Saya telah mengambil kebebasan untuk mengintegrasikan poin Anda ke dalam tubuh jawaban saya.
Marcelo Cantos
73

Setelah beberapa penelitian lebih lanjut saya menemukan presentasi oleh Joe Armstrong.

Dari Erlang - perangkat lunak untuk dunia bersamaan (presentasi) (pada 13 menit):

[Erlang] adalah bahasa konkuren - maksud saya bahwa utas merupakan bagian dari bahasa pemrograman, mereka bukan milik sistem operasi. Itu benar-benar apa yang salah dengan bahasa pemrograman seperti Java dan C ++. Utasnya tidak ada dalam bahasa pemrograman, utas adalah sesuatu dalam sistem operasi - dan mereka mewarisi semua masalah yang mereka miliki dalam sistem operasi. Salah satu masalah adalah rincian sistem manajemen memori. Manajemen memori dalam sistem operasi melindungi seluruh halaman memori, sehingga ukuran terkecil yang dapat dituju adalah ukuran terkecil dari sebuah halaman. Itu sebenarnya terlalu besar.

Jika Anda menambahkan lebih banyak memori ke mesin Anda - Anda memiliki jumlah bit yang sama yang melindungi memori sehingga granularity dari tabel halaman naik - Anda akhirnya menggunakan mengatakan 64kB untuk proses yang Anda tahu berjalan dalam beberapa ratus byte.

Saya pikir itu menjawab jika tidak semua, setidaknya beberapa pertanyaan saya

Jonas
sumber
2
Perlindungan memori pada tumpukan ada karena suatu alasan. Apakah Erlang tidak melindungi tumpukan konteks eksekusi yang berbeda melalui MMU prosesor? (Dan hanya berharap yang terbaik?) Bagaimana jika sebuah thread menggunakan lebih dari tumpukan kecilnya? (Apakah semua alokasi tumpukan diperiksa untuk melihat apakah tumpukan yang lebih besar diperlukan? Apakah tumpukan dapat dipindah?)
Thanatos
2
@Hanatos: Erlang tidak mengizinkan program mengakses memori atau bermain-main dengan stack. Semua alokasi harus melalui runtime yang dikelola, baik heap dan stack. Dengan kata lain: perlindungan perangkat keras tidak berguna karena melindungi terhadap hal-hal yang tidak dapat terjadi. Bahasanya adalah pointer-safe, stack-safe, memory-safe, dan type-safe. Suatu proses tidak dapat menggunakan lebih dari "tumpukan kecil" karena tumpukan tumbuh sesuai kebutuhan. Anda mungkin menganggapnya sebagai kebalikan dari kecil: sangat besar. (Tapi dialokasikan dengan malas.)
Jörg W Mittag
4
Anda harus melihat Sistem Operasi Singularity oleh Microsoft Research. Dalam Singularity, semua kode, kernel, driver perangkat, pustaka, dan program pengguna berjalan di ring 0 dengan hak kernel penuh. Semua kode, kernel, driver perangkat, pustaka, dan program pengguna berjalan dalam satu ruang alamat fisik tunggal tanpa perlindungan memori apa pun. Tim menemukan bahwa jaminan yang dibuat oleh bahasa jauh lebih kuat daripada jaminan yang bisa dibuat oleh MMU, dan pada saat yang sama menggunakan MMU menghabiskan biaya hingga 30% (!!!) dalam kinerja. Jadi, mengapa menggunakan MMU jika bahasa Anda sudah melakukannya?
Jörg W Mittag
1
Sistem Operasi OS / 400 bekerja dengan cara yang sama. Hanya ada satu ruang alamat datar untuk semua program. Dan sebagian besar bahasa yang digunakan saat ini memiliki sifat keamanan yang sama (ECMAScript, Java, C♯, VB.NET, PHP, Perl, Python, Ruby, Clojure, Scala, Kotlin, Groovy, Ceylon, F♯, OCaml, the "Objective" bagian dari "Objective-C", bagian "++" dari "C ++"). Jika bukan karena kode C legacy, dan fitur warisan C ++ dan Objective-C, kita bahkan tidak akan memerlukan memori virtual lagi.
Jörg W Mittag
47

Saya telah mengimplementasikan coroutine dalam assembler, dan mengukur kinerja.

Beralih di antara coroutine, alias proses Erlang, membutuhkan sekitar 16 instruksi dan 20 nanodetik pada prosesor modern. Selain itu, Anda sering mengetahui proses yang Anda gunakan (contoh: proses menerima pesan dalam antriannya dapat diimplementasikan sebagai proses langsung dari proses panggilan ke proses penerimaan) sehingga penjadwal tidak ikut berperan, membuat ini merupakan operasi O (1).

Untuk mengganti utas OS, dibutuhkan sekitar 500-1000 nanodetik, karena Anda memanggil kernel. Penjadwal thread OS mungkin berjalan dalam waktu O (log (n)) atau O (log (log))), yang akan mulai terlihat jika Anda memiliki puluhan ribu, atau bahkan jutaan utas.

Oleh karena itu, proses Erlang lebih cepat dan skala lebih baik karena kedua operasi dasar switching lebih cepat, dan penjadwal berjalan lebih jarang.

Surfer Jeff
sumber
33

Proses Erlang berhubungan (kurang-lebih) dengan utas hijau dalam bahasa lain; tidak ada pemisahan yang diberlakukan OS antara proses. (Mungkin ada pemisahan yang ditegakkan oleh bahasa, tapi itu perlindungan yang lebih rendah meskipun Erlang melakukan pekerjaan yang lebih baik daripada kebanyakan.) Karena mereka jauh lebih ringan, mereka dapat digunakan jauh lebih luas.

Utas OS di sisi lain hanya dapat dijadwalkan pada inti CPU yang berbeda, dan (sebagian besar) dapat mendukung pemrosesan terikat CPU yang independen. Proses OS seperti benang OS, tetapi dengan pemisahan yang ditegakkan dengan OS yang jauh lebih kuat. Harga kemampuan ini adalah bahwa utas OS dan (bahkan lebih lagi) proses lebih mahal.


Cara lain untuk memahami perbedaannya adalah ini. Misalkan Anda akan menulis implementasi Erlang di atas JVM (bukan saran yang sangat gila) maka Anda akan membuat setiap proses Erlang menjadi objek dengan beberapa negara. Anda kemudian akan memiliki kumpulan instance Thread (biasanya berukuran sesuai dengan jumlah core dalam sistem host Anda; itu adalah parameter yang dapat ditala dalam runtime Erlang nyata BTW) yang menjalankan proses Erlang. Pada gilirannya, itu akan mendistribusikan pekerjaan yang harus dilakukan di seluruh sumber daya sistem nyata yang tersedia. Ini cara yang cukup rapi dalam melakukan sesuatu, tetapi sangat bergantungpada kenyataan bahwa setiap proses Erlang individu tidak melakukan banyak hal. Tidak apa-apa tentu saja; Erlang disusun untuk tidak mengharuskan proses individu menjadi kelas berat karena merupakan keseluruhan dari mereka yang menjalankan program.

Dalam banyak hal, masalah sebenarnya adalah salah satu terminologi. Hal-hal yang disebut Erlang proses (dan yang sangat sesuai dengan konsep yang sama dalam CSP, CCS, dan khususnya π-kalkulus) sama sekali tidak sama dengan hal-hal yang bahasa-bahasa dengan warisan C (termasuk C ++, Java, C #, dan banyak lainnya) memanggil suatu proses atau utas. Ada beberapa kesamaan (semua melibatkan beberapa gagasan tentang eksekusi bersamaan) tetapi jelas tidak ada kesetaraan. Jadi berhati-hatilah ketika seseorang mengatakan "proses" kepada Anda; mereka mungkin mengerti itu berarti sesuatu yang sangat berbeda ...

Donal Fellows
sumber
3
Erlang tidak mendekati Pi Calculus. Pi calculus mengasumsikan peristiwa sinkron melalui saluran yang dapat terikat ke variabel. Konsep semacam ini tidak cocok dengan model Erlang sama sekali. Coba Gabung Kalkulus, Erlang lebih dekat dengan itu meskipun masih harus dapat bergabung secara asli pada beberapa pesan dan yang lainnya. Ada sebuah makalah tesis (dan proyek) bernama JErlang berdedikasi yang mengimplementasikannya.
SAYA MEMBERIKAN SARAN LUAR BIASA
Itu semua tergantung pada apa yang sebenarnya Anda lihat pi-kalkulus menjadi (dan Anda dapat memodelkan saluran asinkron dengan saluran sinkron ditambah proses buffer).
Donal Fellows
Anda hanya mengatakan bahwa proses Erlang ringan tetapi Anda tidak menjelaskan mengapa mereka memiliki jejak yang lebih kecil (ringan) dan mengapa mereka memiliki kinerja yang lebih baik daripada benang OS.
Jonas
1
@Jonas: Untuk beberapa jenis tugas (terutama tugas yang berat untuk komputasi) utas OS lebih baik. Ingat, itu bukan tugas yang digunakan Erlang; Erlang berfokus pada memiliki sejumlah besar tugas komunikasi sederhana. Salah satu keuntungan dari melakukan itu adalah bahwa dalam kasus sekelompok tugas yang menyerahkan pekerjaan dan menunggu hasilnya, yang semuanya dapat dilakukan dalam utas OS tunggal pada prosesor tunggal, yang lebih efisien daripada memiliki saklar konteks.
Donal Fellows
Secara teoritis, Anda dapat membuat utas OS menjadi sangat murah juga dengan menggunakan tumpukan yang sangat kecil dan dengan hati-hati mengendalikan jumlah sumber daya khusus utas lainnya yang dialokasikan, tetapi dalam praktiknya cukup bermasalah. (Memprediksi persyaratan stack adalah sedikit seni hitam.) Jadi, bukannya benang OS dirancang khusus untuk menjadi optimal dalam kasus di mana ada lebih sedikit dari mereka (dari urutan jumlah core CPU) dan di mana mereka melakukan lebih signifikan jumlah pemrosesan masing-masing.
Donal Fellows
3

Saya pikir Jonas menginginkan beberapa angka untuk membandingkan thread OS dengan proses Erlang. Penulis Pemrograman Erlang, Joe Armstrong, beberapa waktu lalu menguji skalabilitas pemijahan proses Erlang ke thread OS. Dia menulis server web sederhana di Erlang dan mengujinya terhadap multi-threaded Apache (karena Apache menggunakan thread OS). Ada situs web lama dengan data yang berasal dari tahun 1998. Saya hanya berhasil menemukan situs itu sekali saja. Jadi saya tidak bisa menyediakan tautan. Tetapi informasinya ada di luar sana. Poin utama dari penelitian ini menunjukkan bahwa Apache maksimal hanya di bawah proses 8K, sementara server Erlang yang ditulis tangannya menangani proses 10K +.

Jurnell
sumber
5
Saya pikir Anda berbicara tentang yang ini: sics.se/~joe/apachevsyaws.html Tapi saya bertanya bagaimana erlang membuat benang jadi efisien dibandingkan dengan benang kerlenl.
Jonas
Tautan @Jonas sudah mati. Cuplikan terakhir ada di sini
alvaro g
1
Artikel itu mengatakan: "Apache mati di sekitar 4.000 sesi paralel. Yaws masih berfungsi di lebih dari 80.000 koneksi paralel."
Nathan Long
lihat artikel lengkapnya di citeseerx.ist.psu.edu/viewdoc/... Memang, terbukti tidak mungkin untuk memecahkan server Erlang menggunakan 16 mesin penyerang - meskipun mudah untuk menghentikan server Apache.
Bernhard
1

Karena juru bahasa Erlang hanya perlu khawatir tentang dirinya sendiri, OS memiliki banyak hal lain yang perlu dikhawatirkan.

Francisco Soto
sumber
0

salah satu alasannya adalah proses erlang dibuat bukan di OS, tetapi di evm (mesin virtual erlang), sehingga biayanya lebih kecil.

ratzily
sumber