Non ho tutte le risposte. Spero di poter versare qualche luce su di esso.
Per semplificare le mie precedenti dichiarazioni sui modelli di threading di .NET, è sufficiente sapere che Libreria parallela utilizza Attività e TaskScheduler predefinito per Attività, utilizza il ThreadPool. Più in alto vai nella gerarchia (ThreadPool è in fondo), maggiore è il sovraccarico che hai quando crei gli oggetti. Quel sovraccarico in più certamente non significa che sia più lento, ma è bello sapere che è lì. In definitiva, le prestazioni dell'algoritmo in un ambiente multi-thread si riducono al suo design. Ciò che esegue bene può in modo sequenziale, non si comporta altrettanto bene in parallelo. Ci sono troppi fattori coinvolti per darti regole ferree 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 dare un piccolo esempio.
Permettetemi di affermare che non sono un esperto con le prese e non conosco quasi nulla di Zeroc-Ice. So di bit 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ò fare più richieste dal momento che è bloccata. Usando Socket.Beginxxxxxx (), la richiesta I / O verrà creata e inserita nella coda IRP per il socket e il thread continuerà. Questo significa che il tuo thread potrebbe effettivamente fare migliaia di richieste in un loop senza alcun blocco!
Se sto capendo correttamente, stai utilizzando le chiamate tramite Zeroc-Ice nel tuo codice di test, in realtà non provando a raggiungere un endpoint http. Se è così, posso ammettere che non so come funziona Zeroc-Ice. Tuttavia, suggerirei di seguire il consiglio elencato qui , in particolare la parte: Consider Asynchronous Method Invocation (AMI)
. La pagina mostra questo:
By using AMI, the client regains the thread of control as soon as the invocation has been sent (or, if it cannot be sent immediately, has been queued), allowing the client to use that thread to perform other useful work in the mean time.
Quale sembra essere l'equivalente di ciò che ho descritto sopra usando socket .NET. Potrebbero esserci altri modi per migliorare le prestazioni quando si tenta di eseguire molte mandate, ma inizierei qui o con qualsiasi altro suggerimento elencato in quella pagina. Sei stato molto vago riguardo al design della tua applicazione, quindi posso essere più specifico di quanto non sia stato sopra. Ricorda, non utilizzare più thread di assolutamente necessario per ottenere ciò che hai bisogno, altrimenti probabilmente troverai la tua applicazione molto più lenta di quanto vuoi.
Alcuni esempi in pseudocodice (cercavo di renderlo il più vicino possibile al ghiaccio senza che io dovessi realmente 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);
}
}
Ricorda che più thread! = prestazioni migliori quando provi a inviare socket (o davvero a fare qualcosa). I thread non sono magici in quanto risolveranno automaticamente qualsiasi problema tu stia lavorando. Idealmente, vuoi 1 thread per core, a meno che un thread non passi molto del suo tempo ad aspettare, quindi puoi giustificare di averne di più. L'esecuzione di ogni richiesta nel proprio thread è una cattiva idea, poiché si verificheranno interruttori di contesto e spreco di risorse. (Se vuoi vedere tutto ciò che ho scritto a riguardo, fai clic su modifica e guarda le revisioni precedenti di questo post. L'ho rimosso poiché sembrava solo che il problema principale fosse oscurato.)
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 attaccalo. Otterrai prestazioni migliori se utilizzi un modello asincrono rispetto a un modello sincrono.
Spero che questo aiuti.