Saya menulis server, dan saya mengirim setiap tindakan ke utas terpisah ketika permintaan diterima. Saya melakukan ini karena hampir setiap permintaan membuat kueri basis data. Saya menggunakan perpustakaan threadpool untuk mengurangi pembangunan / penghancuran utas.
Pertanyaan saya adalah: apa titik cutoff yang bagus untuk utas I / O seperti ini? Saya tahu ini hanya perkiraan kasar, tetapi apakah kita berbicara ratusan? Ribuan?
Bagaimana saya mencari tahu apa yang akan terjadi dengan cutoff ini?
EDIT:
Terima kasih atas tanggapan Anda, sepertinya saya hanya perlu mengujinya untuk mengetahui batas jumlah utas saya. Pertanyaannya adalah: bagaimana saya tahu saya telah mencapai langit-langit itu? Apa tepatnya yang harus saya ukur?
Jawaban:
Beberapa orang akan mengatakan bahwa dua utas terlalu banyak - saya tidak cukup di kamp itu :-)
Ini saran saya: ukur, jangan menebak. Satu saran adalah membuatnya dapat dikonfigurasi dan pada awalnya set ke 100, kemudian lepaskan perangkat lunak Anda ke alam liar dan pantau apa yang terjadi.
Jika penggunaan utas Anda mencapai 3, maka 100 terlalu banyak. Jika tetap di 100 untuk sebagian besar hari, menabraknya hingga 200 dan melihat apa yang terjadi.
Anda sebenarnya dapat memiliki kode Anda sendiri memantau penggunaan dan menyesuaikan konfigurasi untuk kali berikutnya dimulai tetapi itu mungkin berlebihan.
Untuk klarifikasi dan elaborasi:
Saya tidak menganjurkan menggulirkan subsistem penggabungan thread Anda sendiri, dengan cara apa pun gunakan yang Anda miliki. Tapi, karena Anda bertanya tentang titik cut-off yang baik untuk utas, saya menganggap implementasi kumpulan utas Anda memiliki kemampuan untuk membatasi jumlah maksimum utas yang dibuat (yang merupakan hal yang baik).
Saya telah menulis utas dan kode penyatuan koneksi basis data dan mereka memiliki fitur-fitur berikut (yang saya percaya sangat penting untuk kinerja):
Yang pertama menetapkan dasar untuk kinerja minimum dalam hal klien kumpulan thread (jumlah utas ini selalu tersedia untuk digunakan). Yang kedua menetapkan batasan pada penggunaan sumber daya oleh utas aktif. Yang ketiga mengembalikan Anda ke baseline dalam waktu tenang sehingga meminimalkan penggunaan sumber daya.
Anda perlu menyeimbangkan penggunaan sumber daya memiliki utas yang tidak terpakai (A) terhadap penggunaan sumber daya karena tidak memiliki cukup utas untuk melakukan pekerjaan (B).
(A) umumnya penggunaan memori (tumpukan dan sebagainya) karena utas yang tidak bekerja tidak akan menggunakan banyak CPU. (B) umumnya akan menunda pemrosesan permintaan saat mereka tiba karena Anda perlu menunggu utas tersedia.
Itu sebabnya Anda mengukur. Saat Anda menyatakan, sebagian besar utas Anda akan menunggu tanggapan dari database sehingga tidak akan berjalan. Ada dua faktor yang memengaruhi berapa banyak utas yang harus Anda izinkan.
Yang pertama adalah jumlah koneksi DB yang tersedia. Ini mungkin merupakan batas yang sulit kecuali Anda dapat meningkatkannya di DBMS - Saya akan menganggap DBMS Anda dapat mengambil jumlah koneksi yang tidak terbatas dalam hal ini (walaupun Anda idealnya juga harus mengukurnya).
Kemudian, jumlah utas yang Anda miliki tergantung pada penggunaan historis Anda. Minimum yang harus Anda jalankan adalah angka minimum yang pernah Anda jalankan + A%, dengan minimum absolut (misalnya, dan membuatnya dapat dikonfigurasi seperti A) 5.
Jumlah utas maksimum adalah histori maksimum + B% Anda.
Anda juga harus memantau perubahan perilaku. Jika, karena alasan tertentu, penggunaan Anda mencapai 100% dari yang tersedia untuk waktu yang signifikan (sehingga akan mempengaruhi kinerja klien), Anda harus meningkatkan maksimum yang diizinkan sampai sekali lagi B% lebih tinggi.
Menanggapi "apa tepatnya yang harus saya ukur?" pertanyaan:
Apa yang harus Anda ukur secara spesifik adalah jumlah maksimum utas yang digunakan secara bersamaan (mis., Menunggu pengembalian dari panggilan DB) yang sedang dimuat. Kemudian tambahkan faktor keamanan 10% misalnya (ditekankan, karena poster lain tampaknya mengambil contoh saya sebagai rekomendasi tetap).
Selain itu, ini harus dilakukan di lingkungan produksi untuk penyetelan. Tidak apa-apa untuk mendapatkan perkiraan sebelumnya, tetapi Anda tidak pernah tahu produksi apa yang akan terjadi (itulah sebabnya semua hal ini harus dapat dikonfigurasi saat runtime). Ini untuk menangkap situasi seperti pengganda tak terduga dari panggilan klien yang masuk.
sumber
Pertanyaan ini telah dibahas dengan cukup menyeluruh dan saya tidak mendapatkan kesempatan untuk membaca semua tanggapan. Tapi di sini ada beberapa hal yang perlu dipertimbangkan sambil melihat batas atas jumlah utas simultan yang dapat hidup berdampingan secara damai dalam sistem yang diberikan.
Sekarang Anda dapat mengatur ukuran tumpukan Anda untuk memasukkan lebih banyak utas tetapi kemudian Anda harus memperhitungkan overhead manajemen ulir (pembuatan / penghancuran dan penjadwalan). Anda dapat menerapkan Affinity CPU ke proses yang diberikan serta ke utas yang diberikan untuk mengikatnya ke CPU tertentu untuk menghindari overhead migrasi utas antara CPU dan menghindari masalah uang tunai.
Perhatikan bahwa seseorang dapat membuat ribuan utas sesuai keinginannya, tetapi ketika Linux kehabisan VM, ia hanya secara acak mulai mematikan proses (dengan demikian utas). Ini untuk menjaga agar profil utilitas tidak dimaksimalkan. (Fungsi utilitas memberi tahu tentang utilitas sistem untuk jumlah sumber daya tertentu. Dengan sumber daya konstan dalam hal ini CPU Cycles and Memory, kurva utilitas semakin rata dengan semakin banyak tugas).
Saya yakin windows kernel scheduler juga melakukan hal semacam ini untuk mengatasi pemanfaatan sumber daya yang berlebihan
[1] http://adywicaksono.wordpress.com/2007/07/10/i-can-not-create-more-than-255-threads-on-linux-what-is-the-solutions/
sumber
Jika utas Anda melakukan segala jenis pekerjaan intensif sumber daya (CPU / Disk) maka Anda jarang akan melihat manfaat di luar satu atau dua, dan terlalu banyak akan mematikan kinerja dengan sangat cepat.
'Kasus terbaik' adalah utas Anda nanti akan macet sementara yang pertama selesai, atau beberapa akan memiliki blok overhead rendah pada sumber daya dengan pertentangan rendah. Kasus terburuk adalah Anda mulai meronta-ronta cache / disk / jaringan dan throughput keseluruhan Anda turun melalui lantai.
Solusi yang baik adalah dengan menempatkan permintaan di kumpulan yang kemudian dikirim ke utas pekerja dari utas-utas (dan ya, menghindari terus-menerus membuat / merusak thread adalah langkah pertama yang bagus).
Jumlah utas aktif dalam kumpulan ini kemudian dapat diubah dan diskalakan berdasarkan temuan profil Anda, perangkat keras yang Anda jalankan, dan hal-hal lain yang mungkin terjadi pada mesin.
sumber
Satu hal yang harus Anda ingat adalah bahwa python (setidaknya versi berbasis C) menggunakan apa yang disebut kunci juru bahasa global yang dapat memiliki dampak besar pada kinerja pada mesin multi-core.
Jika Anda benar-benar membutuhkan python multithreaded maksimal, Anda mungkin ingin mempertimbangkan untuk menggunakan Jython atau sesuatu.
sumber
Seperti yang dikatakan Pax dengan benar, ukurlah, jangan menebak . Apa yang saya lakukan untuk DNSwitness dan hasilnya mengejutkan: jumlah utas yang ideal jauh lebih tinggi dari yang saya kira, kira-kira 15.000 utas untuk mendapatkan hasil tercepat.
Tentu saja, itu tergantung pada banyak hal, itu sebabnya Anda harus mengukur diri sendiri.
Tindakan lengkap (hanya dalam bahasa Prancis) di Combien de fils d'exécution? .
sumber
Saya telah menulis sejumlah aplikasi multi-utas. Saya biasanya mengizinkan jumlah utas potensial untuk ditentukan oleh file konfigurasi. Ketika saya telah mencari pelanggan tertentu, saya telah menetapkan angka yang cukup tinggi sehingga pemanfaatan semua core CPU saya cukup tinggi, tetapi tidak terlalu tinggi sehingga saya mengalami masalah memori (ini adalah sistem operasi 32-bit di waktu).
Dengan kata lain, sekali Anda mencapai beberapa hambatan baik itu CPU, throughput database, disk throughput, dll, menambahkan lebih banyak utas tidak akan meningkatkan kinerja keseluruhan. Tetapi sampai Anda mencapai titik itu, tambahkan lebih banyak utas!
Perhatikan bahwa ini mengasumsikan sistem yang dipermasalahkan didedikasikan untuk aplikasi Anda, dan Anda tidak harus bermain dengan baik (menghindari kelaparan) aplikasi lain.
sumber
Jawaban "big iron" umumnya adalah satu utas per sumber daya terbatas - prosesor (terikat CPU), lengan (terikat I / O), dll - tetapi itu hanya berfungsi jika Anda bisa merutekan pekerjaan ke utas yang benar untuk sumber daya. diakses.
Di mana itu tidak mungkin, pertimbangkan bahwa Anda memiliki sumber daya yang dapat dipertukarkan (CPU) dan sumber daya yang tidak dapat dipertukarkan (senjata). Untuk CPU itu tidak penting untuk menetapkan setiap utas ke CPU tertentu (meskipun itu membantu dengan manajemen cache), tetapi untuk lengan, jika Anda tidak dapat menetapkan utas ke lengan, Anda masuk ke teori antrian dan berapa jumlah optimal untuk menyimpan senjata sibuk. Secara umum saya berpikir bahwa jika Anda tidak dapat merutekan permintaan berdasarkan lengan yang digunakan, maka memiliki 2-3 benang per lengan akan menjadi benar.
Komplikasi muncul ketika unit kerja yang diteruskan ke thread tidak mengeksekusi unit kerja yang cukup atom. Misalnya, Anda mungkin memiliki utas di satu titik mengakses disk, di titik lain menunggu di jaringan. Ini meningkatkan jumlah "celah" di mana utas tambahan dapat masuk dan melakukan pekerjaan yang bermanfaat, tetapi juga meningkatkan peluang utas tambahan untuk mencemari cache masing-masing, dll, dan meredam sistem.
Tentu saja, Anda harus menimbang semua ini terhadap "bobot" utas. Sayangnya, sebagian besar sistem memiliki utas kelas berat (dan apa yang mereka sebut "utas ringan" seringkali bukan utas sama sekali), jadi lebih baik untuk melakukan kesalahan pada sisi yang rendah.
Apa yang saya lihat dalam praktik adalah bahwa perbedaan yang sangat halus dapat membuat perbedaan besar dalam berapa banyak utas yang optimal. Secara khusus, masalah cache dan konflik kunci dapat sangat membatasi jumlah konkurensi praktis.
sumber
Satu hal yang perlu dipertimbangkan adalah berapa banyak core yang ada pada mesin yang akan mengeksekusi kode. Itu merupakan batasan keras tentang berapa banyak utas yang dapat diproses pada waktu tertentu. Namun, jika, seperti dalam kasus Anda, utas diharapkan sering menunggu basis data untuk mengeksekusi kueri, Anda mungkin ingin menyetel utas Anda berdasarkan pada berapa banyak kueri bersamaan yang bisa diproses oleh basis data.
sumber
Saya pikir ini sedikit menghindar dari pertanyaan Anda, tetapi mengapa tidak memasukkannya ke dalam proses? Pemahaman saya tentang jaringan (dari masa lalu yang kabur, saya tidak benar-benar membuat kode jaringan sama sekali) adalah bahwa setiap koneksi yang masuk dapat ditangani sebagai proses yang terpisah, karena jika seseorang melakukan sesuatu yang buruk dalam proses Anda, itu tidak nuke seluruh program.
sumber
ryeguy, saat ini saya sedang mengembangkan aplikasi yang serupa dan nomor utas saya diatur ke 15. Sayangnya jika saya menambahnya pada 20, itu crash. Jadi, ya, saya pikir cara terbaik untuk menangani ini adalah mengukur apakah konfigurasi Anda saat ini memungkinkan lebih atau kurang dari sejumlah X utas.
sumber
Dalam kebanyakan kasus, Anda harus mengizinkan kumpulan utas untuk menangani ini. Jika Anda memposting beberapa kode atau memberikan rincian lebih lanjut, mungkin lebih mudah untuk melihat apakah ada beberapa alasan perilaku default dari kumpulan thread tidak akan menjadi yang terbaik.
Anda dapat menemukan informasi lebih lanjut tentang bagaimana ini seharusnya bekerja di sini: http://en.wikipedia.org/wiki/Thread_pool_pattern
sumber
Sebanyak thread sebagai inti CPU adalah apa yang saya dengar sangat sering.
sumber