darkolite
Messages postés12Date d'inscriptionmardi 20 juillet 2004StatutMembreDernière intervention24 novembre 2006
-
27 sept. 2006 à 15:54
MorpionMx
Messages postés3466Date d'inscriptionlundi 16 octobre 2000StatutMembreDernière intervention30 octobre 2008
-
29 sept. 2006 à 09:41
Bonjour messieurs (dames?)
Je lutte depuis pas mal de temps avec le ThreadPool en C#. Je ne sais pas si c'est d'ailleurs la meilleurs solution. Voila ce que je voudrait faire.
Je récupére une liste de pages internet a récuperer, disons 1000 urls.
J'ai mon code qui fonctionne très bien, pour une url donnée, mon code récupère la page web, la parse pour prendre uniquement les infos qui m'interresse, puis enregistre ces données dans une base de donnée. Un peu a la maniere d'un crawler.
Lorsque je lance ma boucle sur les 1000 urls, ce systeme fonctionne très bien.
J'ai donc décidé de l'optimiser en gagnant du temps. Je voudrai lancer 20 Threads au lieu d'un, et dès qu'un de ces Threads a fini, il reprend le travail avec une nouvelle urls, pour traité les 980 urls suivantes.
Je me suis donc interressé au ThreadPool, car si je comprend bien, c'est justement son but. Je lance mon programme et voila ce qu'il m'arrive : Un beau message d'erreur :
"There were not enough free threads in the ThreadPool object to complete the operation."
Ok, je me renseigne sur le net, j'essaie differente facon, je mets des Thread.sleep partout pour voir comment ca marche... Rien pas moyen.
Je viens de faire un dernier Test, j'ai enlever toutes mes requetes webs, leurs traitements et l'insertion en base, et je l'ai remplacer par un "Thread.Sleep(1000);" Et Surprise, tout a l'air de fonctionner !!! Mon Thread pool est plein assez rapidement, mais quand il est plein il plante pas... il continue avec ces 25 Threads par defaut.
darkolite
Messages postés12Date d'inscriptionmardi 20 juillet 2004StatutMembreDernière intervention24 novembre 2006 29 sept. 2006 à 09:31
Pour finir, je voulais juste dire que pour mon probleme initiale de ThreadPool qui plante avec plus de requete de que Thread max dans le pool, est résolut :
La solution : Passer en . net 2.0., en 1.1 ya pas moyen.
MorpionMx
Messages postés3466Date d'inscriptionlundi 16 octobre 2000StatutMembreDernière intervention30 octobre 200857 27 sept. 2006 à 16:38
Salut
En effet, c'est une bonne idée d'utiliser le pool de Thread.
Celui-ci contient donc 25 Threads / CPU par defaut, et tu peux modifier cette valeur via la méthode SetMaxThreads. Tu peux aussi obtenir le nombre de Threads dispos via la méthode GetAvailableThreads
L'erreur que tu sembles avoir est bizarre, sachant que si il n'y a pas de Thread dispos, les demandes sont mises en file d'attente. D'ailleurs, avec ton dernier essai, ca prouve bien que ca devrait marcher.
On peut avoir un extrait de ton code qui plante, pour voir si y'a pas quelque chose qui cloche ?
Mx
MVP C#
Vous n’avez pas trouvé la réponse que vous recherchez ?
Sauf qu'il préconise d'augmenter le nombre max de thread. Je vais pas le passer a 1000 !!!
J'ai repris leurs code (avec 55 demandes de Thread), si l'on enleve la requete web ca fonctione, on voit le ThreadPool se remplir et finir avec zéro Thread de libre.
Je reteste en rajoutant la requete web... et arrivé a zéro on retrouve l'erreur. "There were not enough free threads in the ThreadPool object to complete the operation."
Je reteste et cette fois ci je passe seulement 20 demandes de Threads. Ca fonctionne, normal on a pas encore rempli le Thread.
Alors pourquoi lorsque le ThreadPool est plein, et qu'on ordonne une requete HttpWebRequest ca plante ?
Mystère mystère.
Si vous voyez une autre solution de gestion de thread automatique... ou un syteme pas trop compliqué...
MoDDiB
Messages postés546Date d'inscriptionmardi 26 novembre 2002StatutMembreDernière intervention 4 mai 20071 27 sept. 2006 à 17:54
Au niveau performance je doutes que tu gagnes réellement quoi que ce soit en utilisant des threads : disons qu'habituellement tu mets 1s par page internet et bien pour 10 threads tu mettras 10s pour qu'ils soient tous terminés : où est le gain ? Ou alors avec un dualCore .Net disperse la charge ?
Si quelqu'un de bien renseigné à une réponse :)
darkolite
Messages postés12Date d'inscriptionmardi 20 juillet 2004StatutMembreDernière intervention24 novembre 2006 28 sept. 2006 à 10:17
Mes requetes mettent 3s en moyenne, pour ensuite moins d'une seconde de traitement/insertion en base. Si je lance 10 requetes en 10s, jvais attendre a peu pres 13 - 15 secondes en tout pour les réponses (c'est vraiment approximatif ce que je dis la), par contre une a une ca fait 10 X 3 soit 30 secondes.
Sur 10 requetes c'est pas très significatif, sur 1000 je pense franchment gagné 30% de tps.
Jvais tester mais pour moi ya pas photo, il vaut mieux balancer 10 resquetes et attendre les réponses que de tout faire une par une. Je me trompe ?
Je ne parle pas du tps de traitement, dual core et tout le reste, vu que le tps de récup des pages est beaucoup plus long, je peux traité 3 ou 4 pages (sans doute plus) pendant que j'en récupère qu'une seule page....
MoDDiB
Messages postés546Date d'inscriptionmardi 26 novembre 2002StatutMembreDernière intervention 4 mai 20071 28 sept. 2006 à 11:04
Donc d'après ce que tu dis plus j'utilises de Thread et plus mon programme occupera le processeur : ce qui veut dire que sans Thread le processeur n'est pas exploité à fond ....
J'aimerais des renseignements de la part d'un connaisseur mais je crois que je vais faire mes tests dans la journée :)
MoDDiB
Messages postés546Date d'inscriptionmardi 26 novembre 2002StatutMembreDernière intervention 4 mai 20071 28 sept. 2006 à 11:36
Dans ton cas précis effectivement je crois que tu peux gagner du temps vu qu'il y a la latence : pendant l'envoie ou la reception de la requete ton programme pourra travailler sur un autre site.
Car dans un autre cas si on te donne 2 projets à faire d'une durée d'une heure chacun et bien en les faisant en même temps ( Threads ) tu mettras tout de même 2 heures...
Mais je viens d'effectuer un test en remplissant un Form avec SetPixel suivit de ce petit calcul :
int a = 0;
for (int i = 0; i < 1000000000; i++)
{
if (i % 2 == 0)
a += i;
else
a -= i;
}
Et bien en éxécutant les méthodes à la suite elles sont éxécutés en 32s et en utilisant un Thread tout le traitement est terminé en 30s : comment cela est-il possible ?
darkolite
Messages postés12Date d'inscriptionmardi 20 juillet 2004StatutMembreDernière intervention24 novembre 2006 28 sept. 2006 à 11:56
Oui et non. Grace au multithreading tu peux faire autre chose en parallele et donc occuper ton proc pendant qu'une autre parti de ton code attend qq chose. Mais bon, avec un seul thread j'arrive aussi a prendre 100% de mon CPU.... Tout dépend de ce que tu fais (acces disques, attente, web, action utilisateur...)
Par contre le fait de mettre le plus possible de Thread ne te garantit pas de meilleurs perf. Pour reprendre mon cas, j'ai 1000 pages web a récupérer, je ne vais pas bourrer mon Thread Pool de thread ca sert a rien, en plus le systeme est limité en nombre de thread et en nombre de connection TCP simultané (50 sous XP je crois). Je vais faire des tests, mais je pense utiliser un Thread Pool de 3 à 10 Threads max. Je ferai le test chronométré pour voir avec combien de Thread j'arrive a faire mes taches le plus rapidement possible.
Apres t'as raison, ca devient hors de mes competences. Je suis pas expert.
Si je me souviens bien, le ThreadPool de base n'est pas le plus efficace en terme de perf, il faudrait que je retrouve le site qui en parle. Ils ont fait des tests avec diverses methodes, tps de traitement, optimisation etc ...)
darkolite
Messages postés12Date d'inscriptionmardi 20 juillet 2004StatutMembreDernière intervention24 novembre 2006 28 sept. 2006 à 16:50
Voila, j'ai fait qq test. J'ai repris le code de crosoft que j'ai légérement modifié.
int intThread = 50;
ThreadPool.SetMaxThreads(intThread, 9000);
int intPages = 1000;
for (int i = 0; i < intPages; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(PoolFunc), i);
}
J'ai fait varié la variable intThread avec les valeurs suivante 1, 5, 10, 20, 50
J'ai fait varié la variable intPages avec les deux valeurs suivante : 100 pages et 1000 pages
Voici ce que ca donne en graphe, l'axe Y représente le tps de traitement totale en seconde, l'axe X le nombre de Thread utilisé dans mon ThreadPool.
La serie 1 correspond à 100 pages
La serie 2 correspond a 1000 pages
J'ai fait 3 test pour chacun des points et j'ai fait une moyenne. La ou j'ai un peu de mal a certifié la véracité de mes résultats c'est que je ne suis pas maitre d'internet, des taux de transfert, de la bande passante, de la disponibilité du réseaux etc.
Donc a prendre avec des pincettes.
On voit le tps de traitement plus faible d'environ 40 % avec un pool de thread a 20. J'annonce aucune conclusion car j'ai fait ca rapidos. On remarque aussi qu'avec un pool de 50 ca met autant de tps qu'avec un pool de 10.
Le second graph affiche le traffic moyen observé pendant l'analyse. Pareil, c'est avec a le pool a 20 qu'on observe la meilleure vitesse. Normal, pour la meme quantité de donnée, comme on a mit moins de tps, on a un meilleur telechargement moyen. (unité le kpb)
Voila, ca sert pas a grand chose, mais j'ai fait le test !