Eu não tenho todas as respostas. Espero que eu possa lançar alguma luz sobre isso.
Para simplificar minhas declarações anteriores sobre os modelos de encadeamento do .NET, basta saber que a Parallel Library usa Tasks, e o TaskScheduler for Tasks padrão, usa o ThreadPool. Quanto mais alto você subir na hierarquia (o ThreadPool fica na parte inferior), mais sobrecarga você terá ao criar os itens. Essa sobrecarga extra certamente não significa que é mais lenta, mas é bom saber que está lá. Por fim, o desempenho do seu algoritmo em um ambiente multithread se resume ao seu design. O que executa bem sequencialmente pode não funcionar tão bem em paralelo. Existem muitos fatores envolvidos para fornecer regras rígidas e rápidas, que mudam dependendo do que você está tentando fazer. Como você está lidando com solicitações de rede, tentarei dar um pequeno exemplo.
Deixe-me declarar que não sou especialista em soquetes e não sei quase nada sobre o Zeroc-Ice. Eu sei um pouco sobre operações assíncronas, e é aqui que ele realmente o ajudará. Se você enviar uma solicitação síncrona por meio de um soquete, quando ligar Socket.Receive()
, seu encadeamento será bloqueado até que uma solicitação seja recebida. Isso não é bom. Seu segmento não pode fazer mais solicitações, pois está bloqueado. Usando Socket.Beginxxxxxx (), a solicitação de E / S será feita e colocada na fila do IRP para o soquete, e seu encadeamento continuará. Isso significa que seu encadeamento pode realmente fazer milhares de solicitações em um loop sem nenhum bloqueio!
Se estou entendendo corretamente, você está usando chamadas via Zeroc-Ice em seu código de teste, sem realmente tentar alcançar um ponto de extremidade http. Se for esse o caso, posso admitir que não sei como o Zeroc-Ice funciona. Gostaria, no entanto, sugerem seguindo o conselho aqui , particularmente a parte: Consider Asynchronous Method Invocation (AMI)
. A página mostra isso:
Ao usar a AMI, o cliente recupera o encadeamento de controle assim que a chamada foi enviada (ou, se não puder ser enviada imediatamente, estiver na fila), permitindo que o cliente use esse encadeamento para executar outro trabalho útil nesse meio tempo. .
O que parece ser o equivalente ao que descrevi acima usando soquetes .NET. Pode haver outras maneiras de melhorar o desempenho ao tentar fazer muitos envios, mas eu começaria aqui ou com qualquer outra sugestão listada nessa página. Você tem sido muito vago quanto ao design do seu aplicativo, para que eu possa ser mais específico do que estive acima. Lembre-se de que não use mais threads do que o absolutamente necessário para obter o que você precisa, caso contrário, o aplicativo será executado muito mais lentamente do que o necessário.
Alguns exemplos em pseudocódigo (tentaram torná-lo o mais próximo possível do gelo, sem que eu realmente precisasse aprender):
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();
}
Uma maneira melhor:
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);
}
}
Lembre-se de que mais threads! = Melhor desempenho ao tentar enviar soquetes (ou realmente fazer alguma coisa). Os threads não são mágicos, pois resolverão automaticamente qualquer problema em que você esteja trabalhando. Idealmente, você deseja 1 thread por núcleo, a menos que um thread gaste muito tempo aguardando, você pode justificar ter mais. A execução de cada solicitação em seu próprio encadeamento é uma má idéia, pois as alternâncias de contexto ocorrerão e o desperdício de recursos. (Se você quiser ver tudo o que escrevi sobre isso, clique em editar e veja as revisões anteriores deste post. Eu o removi, pois ele parecia apenas obscurecer o principal problema em questão.)
Definitivamente, você pode fazer essas solicitações em threads, se desejar fazer um grande número de solicitações por segundo. No entanto, não exagere com a criação do encadeamento. Encontre um equilíbrio e fique com ele. Você obterá melhor desempenho se usar um modelo assíncrono versus um síncrono.
Espero que ajude.