2011-03-08 4 views
2

Mon programme C# reçoit beaucoup de données via plusieurs sockets et il semble que j'ai des problèmes de surcharge du cache TCP sur le noyau Windows.
Cela peut être vu par les résultats suivants du tcpdump du serveur:
Mise en cache d'un flux réseau

18: 02: 18,963370 IP xxxx> yyyy.zzz:. ack 10017011 win 0

Quelle structure de données/stratégie utiliseriez-vous pour mettre en cache les données lues afin d'éviter la surcharge sur C#?
Je travaille actuellement avec un délégué pour chaque socket dans un thread séparé qui est appelé après chaque enregistrement lu, mais cela semble être un problème, de sorte que je pourrais avoir besoin de le diviser en deux threads.
Ou devrais-je envisager de peaufiner les paramètres TCP du côté Windows? J'utilise Windows 7.
Y at-il des livres pour l'optimisation du noyau?
J'ai été vraiment aveuglé que le programme est devenu plus lent même si la charge est d'environ 20-25% pour la machine complète et 50-60% sur le noyau le plus chargé.

+1

Très similaire à http://stackoverflow.com/questions/5234277/c-1-socket-client-continous-data/5234427. Je recommanderais la même chose dans votre cas. –

+0

Oui - en effet. Je suis toujours étonné qu'à côté de tcpdump sur la contrepartie, il n'y a pas de véritables indicateurs d'une pile TCP surchargée. C'est apparemment le goulot d'étranglement, même si l'application elle-même semble en bonne santé en regardant les moniteurs de performance dans Windows. – weismat

Répondre

4

Sans trop en savoir plus sur l'architecture de votre programme, je suppose que votre programme lui-même est le goulot d'étranglement. Si votre application n'utilise pas d'arrière-plan pour collecter les messages TCP et les stocker pour être consommés par le code qui effectue le «gros travail», alors votre programme lit le tampon existant, puis traite ce qu'il contient pendant que le tampon TCP se recharge . Ce cercle vicieux ne peut avoir qu'une seule fin; Finalement, le tampon débordera en attendant que votre programme finisse de traiter ce qu'il a reçu la dernière fois.

Je chercherais à refactoriser votre réception TCP dans un modèle de type ETL. Vous avez besoin d'un thread chargé d'écouter l'entrée TCP, d'extraire les données du tampon et de les mettre en file d'attente dans une collection visible par le reste du programme. Il ne devrait rien faire d'autre que de retirer les données du tampon et de placer les messages bruts dans cette file d'attente, et il devrait le faire aussi vite que possible.

Avec les messages reçus en mémoire, le reste de votre programme peut prendre presque autant de temps qu'il veut consommer chaque message. Vous devez toujours vous assurer que vous ne surchargez pas cette file d'attente en mémoire, mais comme un seul objet .NET peut référencer jusqu'à 2 Go de mémoire, vous risquez beaucoup moins de rencontrer des problèmes. Si vous débordez cette file d'attente dans le programme, vous devez soit rendre le traitement plus efficace, soit lancer plus de threads à cette deuxième étape du processus.

+0

Le programme ne plante pas normalement, mais le serveur interrompt occasionnellement une connexion. L'architecture actuelle a un thread par socket et un délégué pour chaque élément - je suppose que je vais devoir tester plusieurs méthodes de mise en cache, mais une collection de blocage semble être un candidat viable. Cela dépend un peu si l'analyse/décompression doit être l'un des threads du lecteur ou non. Merci pour le conseil. – weismat

+0

Après quelques tests, j'ai fini par travailler avec un objet partagé avec un tableau d'octets, un décalage et une longueur utilisée. J'ai essayé de partager une collection de flux de mémoire, mais la surcharge semblait trop grande (après quelques exceptions de mémoire insuffisante). – weismat