2010-03-25 6 views
10

Tout ce que j'ai lu sur les sockets dans .NET dit que le modèle asynchrone donne de meilleures performances (en particulier avec le nouveau SocketAsyncEventArgs qui économise sur l'allocation).Vs de synchronisation. La performance des Sockets Async en .NET

Je pense que cela a du sens si nous parlons d'un serveur avec de nombreuses connexions client où il n'est pas possible d'allouer un thread par connexion. Ensuite, je peux voir l'avantage d'utiliser les threads ThreadPool et d'obtenir des rappels asynchrones sur eux.

Mais dans mon application, je suis le client et j'ai juste besoin d'écouter un serveur en envoyant des données de ticks du marché sur une connexion tcp. En ce moment, je crée un seul thread, définissez la priorité sur Highest, et appelez Socket.Receive() avec elle. Mon thread bloque sur cet appel et se réveille une fois que de nouvelles données arrivent.

Si je devais passer ce à un modèle async pour que je reçois un rappel quand il y a de nouvelles données, je vois deux problèmes

  1. Les fils de ThreadPool aura la priorité par défaut il semble qu'ils seront strictement pire que mon propre fil qui a la plus haute priorité.

  2. Je vais quand même devoir tout envoyer à travers un seul thread à un moment donné. Dites que je reçois N callbacks presque en même temps sur N threads différents threadpool me notifiant qu'il y a de nouvelles données. Les tableaux d'octets N qu'ils distribuent ne peuvent pas être traités sur les threads de pool de threads car il n'y a aucune garantie qu'ils représentent N messages de données de marché uniques, car TCP est basé sur les flux. Je vais devoir verrouiller et mettre les octets dans un tableau de toute façon et signaler un autre thread qui peut traiter ce qui est dans le tableau. Donc, je ne suis pas sûr de ce que l'achat de threads N threadpool m'achète.

Est-ce que je pense à ce problème? Y at-il une raison d'utiliser le modèle Async dans mon cas spécifique d'un client connecté à un serveur?

MISE À JOUR:

Je pense donc que j'étais mal-compréhension du motif Async (2) ci-dessus. Je recevrais un rappel sur un thread de travail quand il y avait des données disponibles. Ensuite, je voudrais commencer un autre asynchrone recevoir et obtenir un autre rappel, etc. Je n'obtiendrais pas N callbacks en même temps.

La question est toujours la même. Y at-il une raison pour laquelle les rappels seraient mieux dans ma situation spécifique où je suis le client et seulement connecté à un serveur.

Répondre

5

La partie la plus lente de votre application sera la communication réseau. Il est fort probable que vous ne fassiez presque aucune différence en termes de performances pour un client de connexion à un thread et un en modifiant les choses de cette manière. La communication réseau elle-même éclipsera toutes les autres contributions au temps de traitement ou de changement de contexte.

dire que je reçois N callbacks presque en même temps sur N différents fils de ThreadPool me avertissant que il y a de nouvelles données.

Pourquoi cela se produira-t-il? Si vous avez un socket, vous devez effectuer une opération pour recevoir des données, et vous obtenez exactement un rappel quand c'est fait. Vous décidez ensuite de faire une autre opération. On dirait que vous êtes trop compliqué, même si je simplifie peut-être ce que vous essayez de faire. En résumé, je dirais: choisissez le modèle de programmation le plus simple qui vous donne ce que vous voulez; En considérant les choix disponibles dans votre scénario, il est peu probable qu'ils fassent une différence notable par rapport à la performance que vous choisissiez. Avec le modèle de blocage, vous "gaspillez" un fil qui pourrait faire un vrai travail, mais bon ... peut-être que vous n'avez pas de vrai travail à faire.

+0

Merci pour votre réponse. Tu as raison, je regardais mal cet exemple. Donc, je commence et reçois un rappel sur un thread threadpool quand il y a des données. Donc, je le traite et peut alors décider que je veux continuer à écouter pour plus et obtenir un autre rappel. Mais même si c'est le cas, je ne vois pas comment cela pourrait être plus rapide que d'avoir juste un thread de haute priorité dédié à faire le Receive(). –

+0

Tout d'abord, je éviterais de définir la priorité des threads. Je suis sûr que ce n'est généralement pas recommandé. Mieux vaut laisser tous les threads qui ont du travail obtenir un accès égal au CPU. Deuxièmement, ce que je veux dire, c'est que cela ne sera * pas * plus rapide. La valeur des API async est qu'elles vous permettent d'éviter d'attacher un thread (une ressource coûteuse en raison de la taille d'une pile d'appels) en attente pure, et si vous avez seulement une connexion et un thread, et rien à faire jusqu'à ce que vous récupérer les données, alors il n'y a vraiment pas de gros frais pour attacher un thread. L'exception est si vous utilisez Silverlight, car il a seulement asynchrone. –

+0

"Plus rapide" est presque complètement sans objet dans ce scénario, car ces types de choix seront perdus dans le bruit par rapport au coût de la communication réseau elle-même.Il n'y a littéralement rien à gagner en performance en basculant entre ces techniques. –

3

La règle de performance numéro un est d'essayer de l'améliorer quand il le faut. Je vois que vous parlez des normes mais ne mentionnez jamais les problèmes, si vous n'en avez pas, alors vous n'avez pas besoin de vous inquiéter de ce que disent les normes.

+0

Certes, il n'y a pas de problème maintenant. Mais c'est difficile à mesurer. Je pourrais mettre en place deux versions de l'application, une avec le modèle asynchrone et une avec le modèle de synchronisation et le mesurer. Mais il serait bon de savoir si quelqu'un d'autre a déjà fait cela et peut me dire que async sera plus rapide et pourquoi. –

2

"This class was specifically designed for network server applications that require high performance. "

Si je comprends bien, vous êtes un client ici, ayant seulement
données connexion unique. À cet égard arrive dans l'ordre, consommée par un seul fil.

Vous perdrez probablement des performances si vous les placez à à la place de petites quantités sur des threads séparés, juste pour pouvoir les assembler plus tard en mode sérialisé - et ainsi comme un seul thread - Beaucoup de bruit pour rien.


Vous n'avez pas vraiment besoin d'accélérer cela, vous ne pouvez probablement pas.

Qu'est-ce que vous pouvez faire, est cependant à envoyer des unités de travail à d'autres fils après vous les recevez. Vous n'avez pas besoin de SocketAsyncEventArgs pour cela. Ce pourrait accélérer les choses.

Comme toujours, mesurez & mesure.
Aussi, juste parce que vous pouvez, cela ne signifie pas que vous devriez.
Si la performance est suffisante dans un avenir prévisible, pourquoi compliquer les choses?

+0

Je suis d'accord. C'était aussi ma pensée. Si je pouvais obtenir plusieurs rappels sur plusieurs threads ThreadPool, cela me semble être une mauvaise idée. Mais j'étais sceptique parce que chaque article sur socket perf que j'ai lu pour les sockets .NET dit à quel point les sockets async sont géniaux (et je suis sûr qu'ils sont bien meilleurs pour de nombreuses applications). Je voulais juste m'assurer que je ne manquais pas quelque chose pour mon cas particulier. –