Saya tidak punya semua jawaban. Mudah-mudahan saya dapat menumpahkan beberapa cahaya di atasnya.
Untuk menyederhanakan pernyataan saya sebelumnya tentang model .NET's threading, hanya tahu bahwa Perpustakaan Paralel menggunakan Tugas, dan TaskScheduler default untuk Tugas, menggunakan ThreadPool. Semakin tinggi Anda masuk dalam hierarki (ThreadPool di bagian bawah), semakin banyak overhead yang Anda miliki saat membuat item. Overhead tambahan itu tentu saja tidak berarti lebih lambat, tapi senang mengetahui bahwa itu ada di sana. Pada akhirnya kinerja algoritme Anda dalam lingkungan multi-utas bermuara pada desainnya. Apa yang berkinerja baik secara berurutan mungkin tidak berkinerja juga secara paralel. Ada terlalu banyak faktor yang terlibat untuk memberi Anda aturan keras dan cepat, mereka berubah tergantung pada apa yang Anda coba lakukan. Karena Anda berurusan dengan permintaan jaringan, saya akan mencoba dan memberikan contoh kecil.
Biarkan saya menyatakan bahwa saya bukan ahli soket, dan saya tidak tahu apa-apa tentang Zeroc-Ice. Saya tahu sedikit tentang operasi asinkron, dan ini adalah tempat yang sangat membantu Anda. Jika Anda mengirim permintaan sinkron melalui soket, saat Anda menelepon Socket.Receive()
, utas Anda akan diblokir hingga permintaan diterima. Ini tidak baik. Utas Anda tidak dapat membuat permintaan lagi karena diblokir. Menggunakan Socket.Beginxxxxxx (), permintaan I / O akan dibuat dan dimasukkan ke dalam antrian IRP untuk soket, dan utas Anda akan terus berjalan. Ini artinya, utas Anda sebenarnya dapat membuat ribuan permintaan dalam satu lingkaran tanpa pemblokiran sama sekali!
Jika saya memahami Anda dengan benar, Anda menggunakan panggilan melalui Zeroc-Ice dalam kode pengujian Anda, tidak benar-benar mencoba mencapai titik akhir http. Jika itu masalahnya, saya bisa mengakui bahwa saya tidak tahu cara kerja Zeroc-Ice. Saya akan, bagaimanapun, menyarankan mengikuti saran yang tercantum di sini , terutama bagian: Consider Asynchronous Method Invocation (AMI)
. Halaman menunjukkan ini:
Dengan menggunakan AMI, klien mendapatkan kembali utas kontrol segera setelah doa telah dikirim (atau, jika tidak dapat segera dikirim, telah diantrikan), memungkinkan klien untuk menggunakan utas itu untuk melakukan pekerjaan bermanfaat lainnya dalam waktu yang bersamaan. .
Yang tampaknya setara dengan apa yang saya jelaskan di atas menggunakan soket .NET. Mungkin ada cara lain untuk meningkatkan kinerja ketika mencoba melakukan banyak pengiriman, tetapi saya akan mulai di sini atau dengan saran lain yang tercantum di halaman itu. Anda sudah sangat kabur tentang desain aplikasi Anda, jadi saya bisa lebih spesifik daripada yang saya sudah di atas. Hanya ingat, jangan menggunakan lebih banyak utas daripada yang diperlukan untuk menyelesaikan apa yang perlu Anda lakukan, jika tidak, Anda mungkin akan menemukan aplikasi Anda berjalan jauh lebih lambat dari yang Anda inginkan.
Beberapa contoh dalam pseudocode (mencoba membuatnya sedekat mungkin dengan es tanpa saya benar-benar harus mempelajarinya):
var iterations = 100000;
for (int i = 0; i < iterations; i++)
{
// The thread blocks here waiting for the response.
// That slows down your loop and you're just wasting
// CPU cycles that could instead be sending/receiving more objects
MyObjectPrx obj = iceComm.stringToProxy("whateverissupposedtogohere");
obj.DoStuff();
}
Cara yang lebih baik:
public interface MyObjectPrx : Ice.ObjectPrx
{
Ice.AsyncResult GetObject(int obj, Ice.AsyncCallback cb, object cookie);
// other functions
}
public static void Finished(Ice.AsyncResult result)
{
MyObjectPrx obj = (MyObjectPrx)result.GetProxy();
obj.DoStuff();
}
static void Main(string[] args)
{
// threaded code...
var iterations = 100000;
for (int i = 0; i < iterations; i++)
{
int num = //whatever
MyObjectPrx prx = //whatever
Ice.AsyncCallback cb = new Ice.AsyncCallback(Finished);
// This function immediately gets called, and the loop continues
// it doesn't wait for a response, it just continually sends out socket
// requests as fast as your CPU can handle them. The response from the
// server will be handled in the callback function when the request
// completes. Hopefully you can see how this is much faster when
// sending sockets. If your server does not use an Async model
// like this, however, it's quite possible that your server won't
// be able to handle the requests
prx.GetObject(num, cb, null);
}
}
Ingatlah bahwa ada lebih banyak utas! = Kinerja yang lebih baik ketika mencoba mengirim soket (atau benar-benar melakukan apa pun). Utas bukan sulap karena mereka akan secara otomatis memecahkan masalah apa pun yang sedang Anda kerjakan. Idealnya, Anda ingin 1 utas per inti, kecuali utas menghabiskan banyak waktunya menunggu, maka Anda dapat membenarkan memiliki lebih banyak. Menjalankan setiap permintaan di utasnya sendiri adalah ide yang buruk, karena perubahan konteks akan terjadi dan pemborosan sumber daya. (Jika Anda ingin melihat semua yang saya tulis tentang hal itu, klik edit dan lihat revisi-revisi sebelumnya dari postingan ini. Saya menghapusnya karena sepertinya hanya mengaburkan masalah utama yang ada.)
Anda pasti dapat membuat permintaan ini di utas, jika Anda ingin membuat sejumlah besar permintaan per detik. Namun, jangan berlebihan dengan pembuatan utas. Temukan keseimbangan dan pertahankan. Anda akan mendapatkan kinerja yang lebih baik jika Anda menggunakan model asinkron vs model sinkron.
Saya harap itu membantu.