Non ho tutte le risposte. Spero di poter far un po 'di luce su di esso.
Per semplificare le mie precedenti dichiarazioni sui modelli di threading di .NET, sappi solo che Parallel Library utilizza Tasks e TaskScheduler predefinito per Tasks utilizza ThreadPool. Più in alto vai nella gerarchia (ThreadPool è in fondo), maggiore è il sovraccarico che hai durante la creazione degli articoli. Quel sovraccarico extra certamente non significa che è più lento, ma è bello sapere che è lì. In definitiva, le prestazioni del tuo algoritmo in un ambiente multi-thread si riducono al suo design. Ciò che funziona bene in sequenza potrebbe non funzionare altrettanto bene in parallelo. Ci sono troppi fattori coinvolti per darti regole dure e veloci, cambiano a seconda di ciò che stai cercando di fare. Dato che hai a che fare con le richieste di rete, proverò a fare un piccolo esempio.
Consentitemi di affermare che non sono un esperto di prese e che non so quasi nulla di Zeroc-Ice. So qualcosa sulle operazioni asincrone, ed è qui che ti aiuterà davvero. Se si invia una richiesta sincrona tramite un socket, quando si chiama Socket.Receive()
, il thread si bloccherà fino a quando non viene ricevuta una richiesta. Questo non va bene. La tua discussione non può più fare richieste poiché è bloccata. Usando Socket.Beginxxxxxx (), la richiesta I / O verrà effettuata e inserita nella coda IRP per il socket e il thread continuerà. Ciò significa che il tuo thread potrebbe effettivamente effettuare migliaia di richieste in un ciclo senza alcun blocco!
Se ti sto capendo correttamente, stai usando le chiamate via Zeroc-Ice nel tuo codice di test, non in realtà stai cercando di raggiungere un endpoint http. In tal caso, posso ammettere che non so come funziona Zeroc-Ice. Vorrei, tuttavia, suggeriscono seguendo il consiglio elencati qui , in particolare la parte: Consider Asynchronous Method Invocation (AMI)
. La pagina mostra questo:
Utilizzando AMI, il client riacquista il thread di controllo non appena l'invocazione è stata inviata (o, se non può essere inviata immediatamente, è stata messa in coda), consentendo al client di utilizzare quel thread per eseguire altre attività utili nel frattempo .
Che sembra essere l'equivalente di quello che ho descritto sopra usando i socket .NET. Potrebbero esserci altri modi per migliorare le prestazioni quando provo a fare molti invii, ma vorrei iniziare qui o con qualsiasi altro suggerimento elencato in quella pagina. Sei stato molto vago sulla progettazione della tua applicazione, quindi posso essere più specifico di quanto non sia stato sopra. Ricorda, non utilizzare più thread del necessario per ottenere ciò di cui hai bisogno, altrimenti troverai probabilmente la tua applicazione molto più lenta di quanto desideri.
Alcuni esempi in pseudocodice (ho cercato di renderlo il più vicino possibile al ghiaccio senza che io debba davvero impararlo):
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();
}
Un modo migliore:
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);
}
}
Tieni presente che più thread! = Prestazioni migliori quando provi a inviare socket (o fai davvero qualcosa). I thread non sono magici in quanto risolveranno automaticamente qualsiasi problema su cui stai lavorando. Idealmente, vuoi 1 thread per core, a meno che un thread non stia trascorrendo molto del suo tempo ad aspettare, quindi puoi giustificare di averne di più. Eseguire ogni richiesta nel proprio thread è una cattiva idea, poiché si verificheranno cambi di contesto e spreco di risorse. (Se vuoi vedere tutto ciò che ho scritto al riguardo, fai clic su modifica e guarda le revisioni precedenti di questo post. L'ho rimosso poiché sembrava solo appannare il problema principale a portata di mano.)
Puoi sicuramente fare queste richieste nei thread, se vuoi fare un gran numero di richieste al secondo. Tuttavia, non esagerare con la creazione del thread. Trova un equilibrio e mantienilo. Otterrai prestazioni migliori se usi un modello asincrono rispetto a un modello sincrono.
Spero che aiuti.