Saya khawatir saya "melakukan hal yang salah" di sini, jika demikian hapus saya dan saya minta maaf. Secara khusus, saya gagal melihat bagaimana saya membuat anotasi kecil yang rapi yang dibuat beberapa orang. Namun, saya memiliki banyak kekhawatiran / pengamatan untuk dilakukan pada utas ini.
1) Elemen yang dikomentari dalam pseudo-code di salah satu jawaban populer
result = query( "select smurfs from some_mushroom" );
// twiddle fingers
go_do_something_with_result( result );
pada dasarnya palsu. Jika utasnya adalah komputasi, maka itu bukan jempol memutar, itu melakukan pekerjaan yang diperlukan. Jika, di sisi lain, itu hanya menunggu penyelesaian IO, maka itu tidak menggunakan waktu CPU, inti dari infrastruktur kontrol thread di kernel adalah bahwa CPU akan menemukan sesuatu yang berguna untuk dilakukan. Satu-satunya cara untuk "memutar-mutar ibu jari Anda" seperti yang disarankan di sini adalah dengan membuat loop polling, dan tidak ada orang yang memiliki kode server web yang sebenarnya tidak cukup cakap untuk melakukan itu.
2) "Utas itu sulit", hanya masuk akal dalam konteks berbagi data. Jika pada dasarnya Anda memiliki utas independen seperti halnya saat menangani permintaan web independen, maka threading sederhana, Anda hanya perlu mengkode alur linear cara menangani satu pekerjaan, dan duduk dengan cukup mengetahui bahwa itu akan menangani beberapa permintaan, dan masing-masing akan mandiri secara efektif. Secara pribadi, saya berani mengatakan bahwa bagi sebagian besar programmer, mempelajari mekanisme penutupan / panggilan balik lebih kompleks daripada hanya mengkode versi thread top-to-bottom. (Tapi ya, jika Anda harus berkomunikasi di antara utas-utas, hidup menjadi sangat sulit dengan sangat cepat, tapi kemudian saya tidak yakin bahwa mekanisme penutupan / panggilan balik benar-benar mengubah itu, itu hanya membatasi pilihan Anda, karena pendekatan ini masih dapat dicapai dengan utas Bagaimanapun, itu
3) Sejauh ini, tidak ada yang memberikan bukti nyata mengapa satu jenis konteks tertentu akan lebih atau kurang memakan waktu daripada jenis lainnya. Pengalaman saya dalam membuat kernel multi-tasking (dalam skala kecil untuk embedded controller, tidak ada yang semewah OS "nyata") menunjukkan bahwa ini tidak akan terjadi.
4) Semua ilustrasi yang saya lihat sampai saat ini dimaksudkan untuk menunjukkan seberapa cepat Node dibandingkan webserer lain memiliki cacat yang sangat buruk, namun, mereka cacat dengan cara yang secara tidak langsung menggambarkan satu keuntungan yang pasti akan saya terima untuk Node (dan ini tidak berarti tidak berarti). Node tidak tampak seperti itu perlu (atau bahkan izin, sebenarnya) penyetelan. Jika Anda memiliki model ulir, Anda perlu membuat utas yang memadai untuk menangani beban yang diharapkan. Lakukan ini dengan buruk, dan Anda akan berakhir dengan kinerja yang buruk. Jika ada terlalu sedikit utas, maka CPU idle, tetapi tidak dapat menerima lebih banyak permintaan, membuat terlalu banyak utas, dan Anda akan membuang-buang memori kernel, dan dalam kasus lingkungan Java, Anda juga akan membuang-buang memori tumpukan utama . Sekarang, untuk Java, membuang heap adalah cara pertama, terbaik, untuk mengacaukan kinerja sistem, karena pengumpulan sampah yang efisien (saat ini, ini mungkin berubah dengan G1, tetapi tampaknya juri masih keluar pada titik itu setidaknya pada awal 2013) tergantung pada memiliki banyak tumpukan cadangan. Jadi, ada masalah, selaras dengan terlalu sedikit utas, Anda memiliki CPU yang menganggur dan throughput yang buruk, selaras dengan terlalu banyak, dan rusak dengan cara lain.
5) Ada cara lain di mana saya menerima logika klaim bahwa pendekatan Node "lebih cepat dengan desain", dan ini dia. Sebagian besar model utas menggunakan model sakelar konteks irisan waktu, berlapis di atas model preemptive yang lebih tepat (peringatan penilaian nilai :) dan lebih efisien (bukan penilaian nilai). Ini terjadi karena dua alasan, pertama, sebagian besar programmer tampaknya tidak memahami preemption prioritas, dan kedua, jika Anda belajar threading di lingkungan windows, ada rentang waktu apakah Anda suka atau tidak (tentu saja, ini memperkuat poin pertama terutama versi pertama Java menggunakan preemption prioritas pada implementasi Solaris, dan timeslicing di Windows. Karena kebanyakan programmer tidak mengerti dan mengeluh bahwa "threading tidak berfungsi di Solaris" mereka mengubah model menjadi kutu waktu di mana-mana). Bagaimanapun, intinya adalah bahwa penetapan waktu membuat switch konteks tambahan (dan mungkin tidak perlu). Setiap saklar konteks membutuhkan waktu CPU, dan waktu itu secara efektif dihilangkan dari pekerjaan yang dapat dilakukan pada pekerjaan nyata yang ada. Namun, jumlah waktu yang diinvestasikan dalam pengalihan konteks karena penentuan waktu tidak boleh lebih dari persentase yang sangat kecil dari keseluruhan waktu, kecuali jika sesuatu yang sangat aneh terjadi, dan tidak ada alasan saya dapat melihat untuk mengharapkan hal itu terjadi dalam suatu server web sederhana). Jadi, ya, saklar konteks berlebih yang terlibat dalam pengaturan waktu tidak efisien (dan ini tidak terjadi dan waktu itu secara efektif dihilangkan dari pekerjaan yang dapat dilakukan pada pekerjaan nyata yang ada. Namun, jumlah waktu yang diinvestasikan dalam pengalihan konteks karena penentuan waktu tidak boleh lebih dari persentase yang sangat kecil dari keseluruhan waktu, kecuali jika sesuatu yang sangat aneh terjadi, dan tidak ada alasan saya dapat melihat untuk mengharapkan hal itu terjadi dalam suatu server web sederhana). Jadi, ya, saklar konteks berlebih yang terlibat dalam pengaturan waktu tidak efisien (dan ini tidak terjadi dan waktu itu secara efektif dihilangkan dari pekerjaan yang dapat dilakukan pada pekerjaan nyata yang ada. Namun, jumlah waktu yang diinvestasikan dalam pengalihan konteks karena penentuan waktu tidak boleh lebih dari persentase yang sangat kecil dari keseluruhan waktu, kecuali jika sesuatu yang sangat aneh terjadi, dan tidak ada alasan saya dapat melihat untuk mengharapkan hal itu terjadi dalam suatu server web sederhana). Jadi, ya, saklar konteks berlebih yang terlibat dalam pengaturan waktu tidak efisien (dan ini tidak terjadikernel threads sebagai aturan, btw) tetapi perbedaannya adalah beberapa persen dari throughput, bukan jenis faktor bilangan bulat yang tersirat dalam klaim kinerja yang sering tersirat untuk Node.
Ngomong-ngomong, permintaan maaf untuk semua itu panjang dan kasar, tapi aku benar-benar merasa sejauh ini, diskusi belum membuktikan apa-apa, dan aku akan senang mendengar dari seseorang dalam salah satu situasi ini:
a) penjelasan nyata mengapa Node harus lebih baik (di luar dua skenario yang telah saya uraikan di atas, yang pertama (tuning yang buruk) Saya percaya adalah penjelasan nyata untuk semua tes yang saya lihat sejauh ini. ([edit ], sebenarnya, semakin saya memikirkannya, semakin saya bertanya-tanya apakah memori yang digunakan oleh sejumlah besar tumpukan mungkin signifikan di sini. Ukuran tumpukan standar untuk utas modern cenderung cukup besar, tetapi memori dialokasikan oleh sistem acara berbasis penutupan hanya akan menjadi apa yang dibutuhkan)
b) tolok ukur nyata yang benar-benar memberikan peluang yang adil ke server pilihan yang diulir. Setidaknya dengan cara itu, saya harus berhenti percaya bahwa klaim pada dasarnya salah;> (sunting) yang mungkin agak lebih kuat dari yang saya maksudkan, tetapi saya merasa bahwa penjelasan yang diberikan untuk manfaat kinerja tidak lengkap di terbaik, dan tolok ukur yang ditunjukkan tidak masuk akal).
Ceria, Toby
select()
lebih cepat daripada pertukaran konteks thread.