Je n'ai pas toutes les réponses. Espérons que je peux apporter un peu de lumière sur elle.
Pour simplifier mes déclarations précédentes sur les modèles de threads de .NET, sachez simplement que la bibliothèque parallèle utilise des tâches et que le TaskScheduler par défaut pour les tâches utilise le ThreadPool. Plus vous montez dans la hiérarchie (ThreadPool est en bas), plus vous avez de frais généraux lors de la création des éléments. Ce surcoût supplémentaire ne signifie certainement pas qu'il est plus lent, mais il est bon de savoir qu'il est là. En fin de compte, les performances de votre algorithme dans un environnement multithread se résument à sa conception. Ce qui fonctionne bien séquentiellement peut ne pas fonctionner aussi bien en parallèle. Il y a trop de facteurs impliqués pour vous donner des règles dures et rapides, ils changent en fonction de ce que vous essayez de faire. Puisque vous traitez des demandes de réseau, je vais essayer de donner un petit exemple.
Permettez-moi de dire que je ne suis pas un expert des prises, et je ne sais pratiquement rien de Zeroc-Ice. Je connais un peu les opérations asynchrones, et c'est là que cela vous aidera vraiment. Si vous envoyez une demande synchrone via un socket, lorsque vous appelez Socket.Receive()
, votre thread se bloquera jusqu'à ce qu'une demande soit reçue. Ce n'est pas bon. Votre thread ne peut plus faire de demande car il est bloqué. À l'aide de Socket.Beginxxxxxx (), la demande d'E / S sera effectuée et placée dans la file d'attente IRP pour le socket, et votre thread continuera. Cela signifie que votre thread pourrait réellement faire des milliers de demandes dans une boucle sans aucun blocage!
Si je vous comprends bien, vous utilisez des appels via Zeroc-Ice dans votre code de test, sans vraiment essayer d'atteindre un point de terminaison http. Si c'est le cas, je peux admettre que je ne sais pas comment fonctionne Zeroc-Ice. Je voudrais cependant vous suggérons de suivre les conseils énumérés ici , en particulier la partie: Consider Asynchronous Method Invocation (AMI)
. La page montre ceci:
En utilisant AMI, le client retrouve le thread de contrôle dès que l'invocation a été envoyée (ou, si elle ne peut pas être envoyée immédiatement, a été mise en file d'attente), ce qui permet au client d'utiliser ce thread pour effectuer d'autres travaux utiles dans l'intervalle .
Ce qui semble être l'équivalent de ce que j'ai décrit ci-dessus en utilisant des sockets .NET. Il peut y avoir d'autres façons d'améliorer les performances lorsque vous essayez de faire beaucoup d'envois, mais je commencerais ici ou avec toute autre suggestion répertoriée sur cette page. Vous avez été très vague sur la conception de votre application, je peux donc être plus précis que je ne l'ai été ci-dessus. N'oubliez pas, n'utilisez pas plus de threads que ce qui est absolument nécessaire pour faire ce dont vous avez besoin, sinon vous trouverez probablement votre application beaucoup plus lente que vous le souhaitez.
Quelques exemples en pseudocode (j'ai essayé de le rapprocher le plus possible de la glace sans que je doive réellement l'apprendre):
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();
}
Une meilleure façon:
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);
}
}
Gardez à l'esprit que plus de threads! = De meilleures performances lorsque vous essayez d'envoyer des sockets (ou vraiment faire quoi que ce soit). Les threads ne sont pas magiques car ils résoudront automatiquement le problème sur lequel vous travaillez. Idéalement, vous voulez 1 thread par cœur, à moins qu'un thread ne passe la plupart de son temps à attendre, alors vous pouvez justifier d'en avoir plus. Exécuter chaque demande dans son propre thread est une mauvaise idée, car des changements de contexte se produiront et un gaspillage de ressources. (Si vous voulez voir tout ce que j'ai écrit à ce sujet, cliquez sur modifier et consultez les dernières révisions de ce post. Je l'ai supprimé car il ne semblait que brouiller le problème principal.)
Vous pouvez certainement faire ces requêtes dans des threads, si vous voulez faire un grand nombre de requêtes par seconde. Cependant, n'allez pas trop loin avec la création de threads. Trouvez un équilibre et respectez-le. Vous obtiendrez de meilleures performances si vous utilisez un modèle asynchrone par rapport à un modèle synchrone.
J'espère que ça aide.