Comment faire pour déterminer le nombre optimal de threads pour les temps de latence élevé des demandes de réseau?
Je suis en train d'écrire un utilitaire qui doit faire des milliers de demandes de réseau. Chaque demande ne reçoit qu'un seul, petit paquet en réponse (similaire à la commande ping), mais peut prendre plus de quelques secondes. Le traitement de chaque réponse complète dans un (simple) de ligne de code.
Le résultat de tout cela est que l'ordinateur n'est pas IO-lié, système de fichier, ou le CPU, il n'est lié que par le temps de latence des réponses.
Ce qui est similaire, mais pas le même que Il y a un moyen pour déterminer le nombre idéal de threads? et Java meilleure façon de déterminer le nombre optimal de threads [dupliquer]... la principale différence est que je ne suis lié par le temps de latence.
Je suis en utilisant un ExecutorService
l'objet pour exécuter les threads et un Queue<Future<Integer>>
pour suivre les threads qui en ont besoin pour avoir des résultats récupérés:
ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
Queue<Future<Integer>> futures = new LinkedList<Future<Integer>>();
for (int quad3 = 0 ; quad3 < 256 ; ++quad3) {
for (int quad4 = 0 ; quad4 < 256 ; ++quad4) {
byte[] quads = { quad1, quad2, (byte)quad3, (byte)quad4 };
futures.add(executorService.submit(new RetrieverCallable(quads)));
}
}
... J'ai ensuite retirer tous les éléments dans la file d'attente et de mettre les résultats dans la structure de données:
int[] result = int[65536]
while(!futures.isEmpty()) {
try {
results[i] = futures.remove().get();
} catch (Exception e) {
addresses[i] = -1;
}
}
Ma première question est: Est-ce une façon raisonnable de suivre tous les threads? Si thread X prend un certain temps, de nombreux autres threads peut se terminer avant que X n'. Sera le pool de threads d'échappement d'attente pour les fentes ouvertes, ou la ExecutorService
objet de gérer le pool de telle manière que les discussions qui ont terminé mais pas encore été traitées être déplacé hors de places disponibles ainsi que les autres threads mon commencer?
Ma deuxième question est ce que les lignes directrices puis-je utiliser pour trouver le nombre optimal de threads pour effectuer ces appels? Je ne sais même pas l'ordre de grandeur des conseils ici. Je sais que ça fonctionne assez bien avec 256 threads, mais semble prendre à peu près le même temps avec 1024 threads. L'utilisation de l'UC est en vol stationnaire autour de 5%, ce qui ne semble pas être un problème. Avec un grand nombre de threads, ce sont tous les indicateurs que je devrais regarder pour comparer les différents numéros? Évidemment, de temps ensemble pour traiter le lot, le temps moyen par thread... quoi d'autre? La mémoire est un problème ici?
OriginalL'auteur seawolf | 2013-10-24
Vous devez vous connecter pour publier un commentaire.
Il va vous choquer, mais vous n'avez pas besoin de threads pour les I/O (quantitativement, cela signifie 0 threads). Il est bon que vous avez étudié que le multithreading ne pas multiplier la bande passante de votre réseau. Maintenant, il est temps de savoir que threads de calcul. Ils ne font pas les (temps de latence) de communication. La communication est réalisée par une carte réseau, ce qui est un autre processus, en cours d'exécution très en parallèle avec le CPU. Il est stupide d'allouer un thread (voir les ressources allouées sont répertoriés par cette messieurs qui prétend que vous avez besoin de 1 thread) juste pour dormir jusqu'à ce que l'adaptateur réseau termine son travail. Vous n'avez pas besoin de threads pour les I/O = vous avez besoin d'0 threads.
Il est logique d'attribuer les threads de calcul à faire en parallèle avec la demande d'e/S(s). La quantité de fils dépendra de la le calcul de la communication ratio et limité par le nombre de cœurs du PROCESSEUR.
Désolé, je dois dire que malgré que vous avez certainement implicite de l'engagement de blocage I/O, de sorte que beaucoup de gens ne comprennent pas cette chose. Prendre le conseiller, l'utilisation des e/S asynchrones et vous verrez que le problème n'existe pas.
Je vois. La construction d'un framewrok sur le dessus des Acteurs, c'est autre chose. Il ne nécessite pas de construire un cadre sur le dessus de la part des Acteurs. Puis-je dire cela?
Eh bien, c'est opiniâtre sujet. Et mon opinion est que les fils sont plus intuitive pour ce type de travail. Et les acteurs sont au vert, léger threads.
Les acteurs sont tout nouveau pour moi, donc je suis vraiment de travail pour comprendre que nous parlons. @AndreyChaschev, votre commentaire est apprécié, oui, les threads sont intuitifs pour cela. Si les acteurs sont vraiment conceptuellement léger threads, puis ils sont l'approche, je suis à la recherche pour. Merci, vous deux!
Oui, ils sont en effet - Scala: Pourquoi sont des Acteurs léger?. Vraiment intéressant ce que vous arriverez en fin de compte.
OriginalL'auteur Val
Comme mentionné dans l'un des sites les réponses que vous consultez, Brian Goetz a traité de ce bien dans sa l'article.
Il semble impliquer que, dans votre situation, vous seriez avisé de recueillir des métriques avant de s'engager sur un nombre de threads.
Mon accent.
OriginalL'auteur OldCurmudgeon
Avez-vous envisagé d'utiliser Les acteurs?
Désolé, je peux m'étendrai pas, car ne l'ai pas beaucoup utilisé cette.
Mise à JOUR
Réponse dans Bon cas d'utilisation de Akka pourrait être utile.
Scala: Pourquoi sont des Acteurs léger?
OriginalL'auteur Andrey Chaschev
Assez sûr dans les circonstances décrites, le nombre optimal de threads est de 1. En fait, c'est étonnamment souvent la réponse à l'une quesion de la forme " combien de threads doit-je utiliser?
Chaque tranche de fil ajoute une charge supplémentaire en termes de pile (et associés GC racines), le changement de contexte et de verrouillage. Cela peut ou ne pas être mesurables: l'effor pour véritablement mesurer dans tous les envoronments est non-trivial. En retour, il y a peu de possibilités de fournir toute prestation en nature, que le traitement n'est ni processeur ni io-lié.
Donc de moins c'est toujours mieux, si seulement pour des raisons de réduction des risques. Et tu ne peux pas avoir moins de 1.
Je vais reformuler ce que pour dire que la réponse est trompeuse. J'ai un prouvable cas où l'augmentation du nombre de threads radicalement réduit le travail d'ensemble que le temps d'exécution. Une autre approche serait d'utiliser asynchrone IO, qui (si j'ai bien compris) peut avoir les mêmes ou plus d'impact sur les performances. En termes de simplicité, cependant, les threads sont plus rapides à se lever et courir, et dans de nombreux cas sont appropriés pour des emplois de ce type, mais à plus petite échelle.
OK, je suis assez humble pour que je peux dire que j'ai mal compris ton post et suis d'accord avec ce que vous obtenez. Dans l'avenir, il serait utile si vous fourni un exemple de stratégie de remplacement. Comme indiqué dans le répondre, les Acteurs sont conceptuellement léger, fils et si je peux l'utiliser ou à un modèle d'accès simultané alors je suis d'accord, en vrai fils sont overkill. "Conceptuellement" est le mot clé ici, j'ai besoin d'une sorte de simultanéité, et le fils sont un moyen raisonnable d'atteindre cet objectif, tout simplement pas de l'ampleur que j'ai besoin.
Désolé, je pensais que l'idée que vous pouvez utiliser les entrées/sorties asynchrones pour quelque chose comme cela allait sans dire.
Elle doit probablement avoir, mais je l'ai fait très peu de simultanéité au fil des années... ça a toujours été quelqu'un d'autre emploi. Donc oui, je savais que la concurrence était nécessaire, mais async I/O n'a pas immédiatement à l'esprit.
OriginalL'auteur soru
Dans nos systèmes à haute performance, nous utilisons le modèle de l'acteur tel que décrit par @Andrey Chaschev.
Le pas. optimale des threads dans votre acteur modèle diffèrent avec votre CPU de la structure et de la façon dont de nombreux processus (Jvm) ne vous lancez par boîte. Notre conclusion est
OriginalL'auteur Alex Suo
Je suppose que l'optimisation souhaités est le temps de traiter toutes les demandes. Vous avez dit que le nombre de demandes est "milliers" de personnes. De toute évidence, le moyen le plus rapide est de délivrer toutes les demandes à la fois, mais cela peut déborder de la couche réseau. Vous devez déterminer combien de connexions simultanées peuvent de la couche réseau de l'ours, et faire de ce numéro d'un paramètre de votre programme.
Ensuite, passer un fil pour chaque demande nécessite beaucoup de mémoire. Vous pouvez éviter cela en utilisant les sockets non bloquant. En Java, il existe 2 options: NIO1 avec des sélecteurs, et NIO2 avec asynchrone canaux. NIO1 est complexe, afin de mieux trouver un ready-made de la bibliothèque et de la réutiliser. NIO2 est simple mais disponible seulement depuis JDK1.7.
Traitement des réponses doit être effectuée sur un pool de threads. Je ne pense pas que le nombre de threads dans le pool de threads affecte grandement les performances globales dans votre cas. Juste faire de l'optimisation en fonction de la taille du pool de threads de 1 au nombre de processeurs disponibles.
Je n'ai pas rencontré une bibliothèque que je le voudrais, j'ai donc commencé ma propre github.com/rfqu/pipeline/tree/master/pipeline-nio Au moins, il est compact et facile à comprendre.
OriginalL'auteur Alexei Kaigorodov
Une réponse partielle, mais j'espère que cela aide. Oui, la mémoire peut être un problème: Java se réserve 1 MO de pile de thread par défaut (au moins sur Linux amd64). Donc, avec un peu de GO de RAM dans votre coffre, ce qui limite votre nombre de threads à quelques milliers.
Vous pouvez tune ce avec un drapeau comme
-XX:ThreadStackSize=64
. Qui vous donnent de 64 ko, ce qui est amplement suffisant dans la plupart des situations.Vous pouvez également déplacer loin de filetage entièrement et utilisation epoll pour répondre aux demandes de réponses. C'est beaucoup plus évolutif mais je n'ai aucune expérience pratique de le faire en Java.
Malheureusement, je suis en cours d'exécution dans un environnement où je suis limité à 4 go de mémoire RAM totale, de sorte que même si j'augmente la taille de la pile, je ne peux pas augmenter mon thread disponibilité par beaucoup.
OriginalL'auteur Thomas