Je me suis dit que j'allais profiter de .NET pour voir si
l'utilisation des "io completion ports" (IOCP) et "asynchronous io"
(AIO) est facilitée. J'ai été agréablement surpris pas la simplicité
de la chose, ThreadPool et autres nombreuses BeginXXX/EndXXX...
Alors il est temps pour un petit "benchmarking".
Annexe :
========= > Voici quelques détails sur le déroulement des tests. Si le code source
vous intéresse, faites-moi signe.
Serveur .NET :
----------------
Un thread boucle sur des accept au moyen de la classe TCPListener.
A chaque connexion, ThreadPool.QueueUserWorkItem().
Le traitement des données est fait come suit :
Un buffer de 1024 octets par client est alloué,
BeginReceive/EndReceive le remplit, BeginSend/EndSend est ensuite
appelé sur ce buffer et ainsi de suite.
Serveur Win32 :
-----------------
Le thread principal boucle sur accept().
A chaque connexion un thread est créé et la SOCKET est passée en
paramètre (CreateThread())
Le traitement des données est fait comme suit :
Un buffer de 1024 octets est alloué, puis il est rempli par un recv()
bloquant, et vidé par un send() bloquant et ainsi de suite.
Programme de tests :
----------------------
Ce programme crée NB_THREADS threads. Chaque thread répète PASSES fois
les opérations suivantes (dans l'ordre) :
-> crée NB_SOCKETS SOCKETs
-> connecte toutes les SOCKETs
-> NB_QUOTES fois :
-> envoie un message sur tous les SOCKETs
-> reçoit le message sur tous les SOCKETs
J'ai choisi NB_THREADS=5, NB_SOCKETS ce qui fait typiquement 400
clients simultanés, NB_QUOTES ce qui fait environ 1000 octets
envoyés par client, et PASSESP (chaque thread transfère 4 Mo).
Au total 40 Mo sont envoyés, ce qui sur une connexion 100 Mb/s ne
devrait pas prendre plus de 10 sec (4 sec étant le minimum théorique).
Je me suis dit que j'allais profiter de .NET pour voir si
l'utilisation des "io completion ports" (IOCP) et "asynchronous io"
(AIO) est facilitée. J'ai été agréablement surpris pas la simplicité
de la chose, ThreadPool et autres nombreuses BeginXXX/EndXXX...
Alors il est temps pour un petit "benchmarking".
Annexe :
========= > Voici quelques détails sur le déroulement des tests. Si le code source
vous intéresse, faites-moi signe.
Serveur .NET :
----------------
Un thread boucle sur des accept au moyen de la classe TCPListener.
A chaque connexion, ThreadPool.QueueUserWorkItem().
Le traitement des données est fait come suit :
Un buffer de 1024 octets par client est alloué,
BeginReceive/EndReceive le remplit, BeginSend/EndSend est ensuite
appelé sur ce buffer et ainsi de suite.
Serveur Win32 :
-----------------
Le thread principal boucle sur accept().
A chaque connexion un thread est créé et la SOCKET est passée en
paramètre (CreateThread())
Le traitement des données est fait comme suit :
Un buffer de 1024 octets est alloué, puis il est rempli par un recv()
bloquant, et vidé par un send() bloquant et ainsi de suite.
Programme de tests :
----------------------
Ce programme crée NB_THREADS threads. Chaque thread répète PASSES fois
les opérations suivantes (dans l'ordre) :
-> crée NB_SOCKETS SOCKETs
-> connecte toutes les SOCKETs
-> NB_QUOTES fois :
-> envoie un message sur tous les SOCKETs
-> reçoit le message sur tous les SOCKETs
J'ai choisi NB_THREADS=5, NB_SOCKETS ce qui fait typiquement 400
clients simultanés, NB_QUOTES ce qui fait environ 1000 octets
envoyés par client, et PASSESP (chaque thread transfère 4 Mo).
Au total 40 Mo sont envoyés, ce qui sur une connexion 100 Mb/s ne
devrait pas prendre plus de 10 sec (4 sec étant le minimum théorique).
Je me suis dit que j'allais profiter de .NET pour voir si
l'utilisation des "io completion ports" (IOCP) et "asynchronous io"
(AIO) est facilitée. J'ai été agréablement surpris pas la simplicité
de la chose, ThreadPool et autres nombreuses BeginXXX/EndXXX...
Alors il est temps pour un petit "benchmarking".
Annexe :
========= > Voici quelques détails sur le déroulement des tests. Si le code source
vous intéresse, faites-moi signe.
Serveur .NET :
----------------
Un thread boucle sur des accept au moyen de la classe TCPListener.
A chaque connexion, ThreadPool.QueueUserWorkItem().
Le traitement des données est fait come suit :
Un buffer de 1024 octets par client est alloué,
BeginReceive/EndReceive le remplit, BeginSend/EndSend est ensuite
appelé sur ce buffer et ainsi de suite.
Serveur Win32 :
-----------------
Le thread principal boucle sur accept().
A chaque connexion un thread est créé et la SOCKET est passée en
paramètre (CreateThread())
Le traitement des données est fait comme suit :
Un buffer de 1024 octets est alloué, puis il est rempli par un recv()
bloquant, et vidé par un send() bloquant et ainsi de suite.
Programme de tests :
----------------------
Ce programme crée NB_THREADS threads. Chaque thread répète PASSES fois
les opérations suivantes (dans l'ordre) :
-> crée NB_SOCKETS SOCKETs
-> connecte toutes les SOCKETs
-> NB_QUOTES fois :
-> envoie un message sur tous les SOCKETs
-> reçoit le message sur tous les SOCKETs
J'ai choisi NB_THREADS=5, NB_SOCKETS ce qui fait typiquement 400
clients simultanés, NB_QUOTES ce qui fait environ 1000 octets
envoyés par client, et PASSESP (chaque thread transfère 4 Mo).
Au total 40 Mo sont envoyés, ce qui sur une connexion 100 Mb/s ne
devrait pas prendre plus de 10 sec (4 sec étant le minimum théorique).
> Annexe :
> ========= > > Voici quelques détails sur le déroulement des tests. Si le code
> source vous intéresse, faites-moi signe.
Signe!!
> Annexe :
> ========= > > Voici quelques détails sur le déroulement des tests. Si le code
> source vous intéresse, faites-moi signe.
Signe!!
> Annexe :
> ========= > > Voici quelques détails sur le déroulement des tests. Si le code
> source vous intéresse, faites-moi signe.
Signe!!
> Signe aussi! (mon adresse e-mail est valide)
Merci!
> Signe aussi! (mon adresse e-mail est valide)
Merci!
> Signe aussi! (mon adresse e-mail est valide)
Merci!
> Un truc m'échappe : tu parles des IOCP mais dans ton test "natif" tu
ne les utilises pas.
Quand à .NET, les IOCP ne sont utilisés dans ton exemple que pour les
BeginReceive et BeginSend.
Pourquoi faire un QueueUserWorkItem ici? Il faudrait appeler
BeginReceive directement depuis ton thread qui boucle sur les accept.
Ici tu rajoutes un niveau d'indirection de plus, ce qui pourrait
expliquer les écarts obtenus.
Au total 40 Mo sont envoyés, ce qui sur une connexion 100 Mb/s ne
devrait pas prendre plus de 10 sec (4 sec étant le minimum
théorique).
Ca ca ne veut rien dire, le débit sur un lien ethernet est tout sauf
prévisible ;-)
Quelques remarques en passant :
- je ferais le test en local pour commencer, pour essayer de
m'abstraire le plus possible des aléas du réseau.
- Est-ce que tu as fais tourner plusieurs fois le serveur .NET, ou à
défaut est-ce que tu l'as passé à ngen? Sinon, la JIT-compilation
fausse complètement ton test.
> Un truc m'échappe : tu parles des IOCP mais dans ton test "natif" tu
ne les utilises pas.
Quand à .NET, les IOCP ne sont utilisés dans ton exemple que pour les
BeginReceive et BeginSend.
Pourquoi faire un QueueUserWorkItem ici? Il faudrait appeler
BeginReceive directement depuis ton thread qui boucle sur les accept.
Ici tu rajoutes un niveau d'indirection de plus, ce qui pourrait
expliquer les écarts obtenus.
Au total 40 Mo sont envoyés, ce qui sur une connexion 100 Mb/s ne
devrait pas prendre plus de 10 sec (4 sec étant le minimum
théorique).
Ca ca ne veut rien dire, le débit sur un lien ethernet est tout sauf
prévisible ;-)
Quelques remarques en passant :
- je ferais le test en local pour commencer, pour essayer de
m'abstraire le plus possible des aléas du réseau.
- Est-ce que tu as fais tourner plusieurs fois le serveur .NET, ou à
défaut est-ce que tu l'as passé à ngen? Sinon, la JIT-compilation
fausse complètement ton test.
> Un truc m'échappe : tu parles des IOCP mais dans ton test "natif" tu
ne les utilises pas.
Quand à .NET, les IOCP ne sont utilisés dans ton exemple que pour les
BeginReceive et BeginSend.
Pourquoi faire un QueueUserWorkItem ici? Il faudrait appeler
BeginReceive directement depuis ton thread qui boucle sur les accept.
Ici tu rajoutes un niveau d'indirection de plus, ce qui pourrait
expliquer les écarts obtenus.
Au total 40 Mo sont envoyés, ce qui sur une connexion 100 Mb/s ne
devrait pas prendre plus de 10 sec (4 sec étant le minimum
théorique).
Ca ca ne veut rien dire, le débit sur un lien ethernet est tout sauf
prévisible ;-)
Quelques remarques en passant :
- je ferais le test en local pour commencer, pour essayer de
m'abstraire le plus possible des aléas du réseau.
- Est-ce que tu as fais tourner plusieurs fois le serveur .NET, ou à
défaut est-ce que tu l'as passé à ngen? Sinon, la JIT-compilation
fausse complètement ton test.