L'amélioration de la performance de multithread HttpWebRequests dans .NET
Je suis en train d'essayer de mesurer le débit d'un webservice.
Pour ce faire, j'ai écrit un petit outil qui envoie en permanence des demandes et lit les réponses d'un nombre de threads.
Le contenu de la boucle interne de chaque thread ressemble à ceci:
public void PerformRequest()
{
WebRequest webRequest = WebRequest.Create(_uri);
webRequest.ContentType = "application/ocsp-request";
webRequest.Method = "POST";
webRequest.Credentials = _credentials;
webRequest.ContentLength = _request.Length;
((HttpWebRequest)webRequest).KeepAlive = false;
using (Stream st = webRequest.GetRequestStream())
st.Write(_request, 0, _request.Length);
using (HttpWebResponse httpWebResponse = (HttpWebResponse)webRequest.GetResponse())
using (Stream responseStream = httpWebResponse.GetResponseStream())
using (BufferedStream bufferedStream = new BufferedStream(responseStream))
using (BinaryReader reader = new BinaryReader(bufferedStream))
{
if (httpWebResponse.StatusCode != HttpStatusCode.OK)
throw new WebException("Got response status code: " + httpWebResponse.StatusCode);
byte[] response = reader.ReadBytes((int)httpWebResponse.ContentLength);
httpWebResponse.Close();
}
}
Il semble fonctionner ok, sauf que quelque chose semble être un facteur limitant de l'outil. Si je exécuter deux instances de l'outil à chaque 40 fils, je reçois beaucoup plus de débit qu'une seule instance avec 80 fils.
J'ai trouvé le ServicePointManager.DefaultConnectionLimit bien, que j'ai mis à 10000 (et il ne fait aucune différence si je l'ai mis à partir de l'app.config comme suggéré par Jader Dias).
Existe-il d'autres paramètres .NET ou sur ma machine qui peuvent influencer la performance? (Je suis sous Vista, mais je vois le même problème sur Windows Server 2003).
Peut-être certaines restrictions sur le nombre de connexions d'un seul processus peut faire?
- Je sais que cette question est à partir de '08, mais vous pouvez être intéressé par certains des nouveaux le parallélisme des fonctions de .net 4.5
- ceux parallélisme fonctionnalités sera plus facile à mettre en œuvre la solution, mais ils ne suffiront pas à résoudre le problème de la DefaultConnectionLimit.
Vous devez vous connecter pour publier un commentaire.
Vous devez définir le paramètre maxconnection à l'app.config ou web.fichier de configuration:
Valeurs jusqu'à 100 fonctionne très bien avec Windows XP.
Mise à jour: je viens de constater que la méthode ci-dessus est une autre façon de définir le Système.Net.ServicePointManager.DefaultConnectionLimit
ServicePointManager.DefaultConnectionLimit
n'a pas).ServicePointManager.DefaultConnectionLimit
doit être réglée avant la ServicePoint est créé et ne fonctionne pas en Monoil pourrait être la limite de connexion qui a été imposé récemment.
http://www.speedguide.net/read_articles.php?id=1497
et
http://www.mydigitallife.info/2007/04/09/windows-vista-tcpipsys-connection-limit-patch-for-event-id-4226/
avez-vous tenté d'augmenter le max de connexions dans les paramètres réseau?
http://msdn.microsoft.com/en-us/library/fb6y0fyc.aspx
Garder à l'esprit le code multithread peut toujours provoquer des conflits sur les ressources partagées et même si vous n'êtes pas explicitement le partage de tout ce que vous pourriez être en utilisant des classes qui sont le partage de ressources sous les couvertures.
Si vous êtes vraiment obtenir de meilleures performances avec 2 40 thread exe de 1 80 thread exe puis vous aurez besoin pour commencer votre enquête avec des ressources partagées. Et si c'est le cas, le code que vous avez cité est bien moins intéressant que le code qui crée et gère les threads.
L'autre chose que j'avais à jeter, il y a, il existe plusieurs outils que vous pouvez obtenir qui va faire ce genre de chose pour vous d'une manière générique. Voir http://support.microsoft.com/kb/231282. Également inclus dans Visual Studio (je ne suis pas sûr de ce que sku) est une nouvelle génération d'application web tests de performance des outils. Et je suis sûr que si vous avez regardé, vous pouvez trouver certains non-MME des trucs aussi.
Il y a deux aspects importants w.r.t:
Un aspect est comme suggéré par tous, la nombre de connexions TCP été utilisé par le client
(généralement mieux si ces connexions sont conservées (garder vivant = true)) pour les détails, se référer à : http://msdn.microsoft.com/en-us/library/system.net.servicepoint.connectionlimit(v=vs. 110).aspx, Comment et où la connexion TCP a été créé en httpwebrequest, et comment est-il lié à servicepoint? , Pourquoi Système.Net.ServicePoint.ConnectionLimit utilise 7FFFFFFF' (Int32.MaxValue/2147483647) lorsqu'un client se connecte à un service sur 'localhost'? , Système.Net.ServicePointManager.DefaultConnectionLimit et .MaxServicePointIdleTime )
Deuxième aspect est plutôt que l'utilisation de plusieurs nouveaux threads/ou de l'utilisation de threads de travail à faire travailler en parallèle à l'aide des appels synchrones (comme httpwebrequest.getrequeststream) dans l'extrait de code, embrassant async modèle entièrement (par ex, commencer/endrequeststream, ou une nouvelle tâche de variations). De cette façon, CPU sera toujours occupé et laissez-I/O port de terminaison du thread il suffit d'envoyer la réponse à un travailleur (pool de threads thread en invoquant de rappel. (vous pouvez vous référer à: Comment ne .FILET de faire usage de IO Fils ou IO Ports de fin?, http://blog.marcgravell.com/2009/02/async-without-pain.html, HttpWebRequest et I/O ports de fin d' )
Comment êtes-vous de la création de votre fils? Je suppose que, puisque vous savez que vous avez 80 threads, vous n'êtes pas en utilisant le gestionnaire de pool de threads, car avec le gestionnaire de pool de threads, vous pouvez demander autant de threads que vous le souhaitez et vous obtiendrez seulement 25 threads actifs à la fois. Si vous créez les threads à la main avec un tableau alors vous aurez vraiment obtenir autant que vous le souhaitez, cependant, ils sont encore dans le processus même de l'espace, de façon à ce que pourrait limiter de plus de threads s'exécutant dans des processus séparés.
Vous pouvez également regarder dans quel appartement de style que les fils sont se créé avec, je crois que la classe Thread ctor utilise STA par défaut. Essayez de MTA et voir si ils ont une incidence sur les performances.