2016-02-02 1 views
0

Je suis en train de tester deux applications avec des sockets TCP. La première application utilise de nouveaux appels de socket RIO, la deuxième application utilise des appels de socket Winsock classiques. Les deux applications envoient une seule chaîne à un serveur. Je leur ai fait utiliser des sockets non-bloquants et désactivé l'algorithme de Nagle. Quand je mesure le temps qu'il faut pour exécuter les envois, contrairement à mes attentes, le socket classique est plus rapide. Quelle est la raison pour ça?Pourquoi RIOSend est-il plus lent que le socket winapi classique?

Voici mon code:

/* 
    Classic socket 
*/ 
SOCKET ConnectSocket = INVALID_SOCKET; 

// ... socket initialization 

// Make socket non-blocking and disable Nagle's algorithm 
unsigned long mode = 1; 
ioctlsocket(ConnectSocket, FIONBIO, &mode); 
int isOn = 1; 
setsockopt(ConnectSocket, IPPROTO_TCP, TCP_NODELAY, (char *) &isOn, sizeof(int)); 

// Measure exec time 
t1 = __rdtscp(&dum); 
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0); 
t2 = __rdtscp(&dum); 
cout << (t2 - t1)/3000.0f << " 10^-6 sec" << endl; 

/* 
    RIO socket 
*/ 
SOCKET s = WSASocket(
     AF_INET, 
     SOCK_STREAM, 
     IPPROTO_TCP, 
     NULL, 
     0, 
     WSA_FLAG_REGISTERED_IO); 

// ... socket initialization 

// Make socket non-blocking and disable Nagel's algorithm 
unsigned long mode = 1; 
ioctlsocket(s, FIONBIO, &mode); 
int isOn = 1; 
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *)&isOn, sizeof(int)); 

// RIO socket is event-based 
hEvent = WSACreateEvent(); 
RIO_NOTIFICATION_COMPLETION type; 
type.Type = RIO_EVENT_COMPLETION; 
type.Event.EventHandle = hEvent; 
type.Event.NotifyReset = TRUE; 
RIO_CQ complQueue = rioFuncTable.RIOCreateCompletionQueue(1000, &type); 

RIO_RQ requestQueue = rioFuncTable.RIOCreateRequestQueue(
     s, 
     10, 
     1, 
     10, 
     1, 
     complQueue, 
     complQueue, 
     NULL); 

// Init rio buffers 
char *pSndBuffer = new char[sndBufferSize + 1](); 
std::copy(message, message + sndBufferSize, pSndBuffer); // put message to a server here 

RIO_BUFFERID sndBufID = rioFuncTable.RIORegisterBuffer(pSndBuffer, sndBufferSize); 
RIO_BUF sndBuffer; 
sndBuffer.BufferId = sndBufID; 
sndBuffer.Offset = 0; 
sndBuffer.Length = sndBufferSize; 

// Measure exec time 
t1 = __rdtscp(&dum); 
rioFuncTable.RIOSend(requestQueue, &sndBuffer, 1, 0, NULL); 
t2 = __rdtscp(&dum); 
cout << (t2 - t1)/3000.0f << " 10^-6 sec" << endl; 
+1

Etes-vous sûr que 'send()' et 'RIOSend()' réussissent? Vous ne vérifiez pas leurs valeurs de retour pour les erreurs, et ne pas en sortie les valeurs à la console. Puisque les sockets sont en mode non bloquant, 'send()' et 'RIOSend()' peuvent envoyer moins d'octets que ce que vous leur demandez d'envoyer. Peut-être que 'send()' est "plus rapide" car il envoie moins d'octets que "RIOSend()" n'envoie. Vous n'attendez même pas que l'événement de fin de 'RIOSend()' soit signalé avant de récupérer le temps écoulé. Je ne vous vois pas appeler 'RIONotify()' ou 'WSAWaitForMultipleEvents()'. –

+1

D'ailleurs, qu'est-ce qui vous fait penser que RIO sera plus rapide quand même? Lors de l'envoi de petites quantités de données, les performances seront probablement comparables les unes aux autres. C'est lorsque vous commencez à envoyer beaucoup de données sur une période plus longue que RIO dépassera probablement le classique. Mais même alors, MSDN affirme que RIO est "* ciblé ** principalement pour les applications serveur **, *", de sorte que les clients ne verront peut-être pas un gain aussi important que ce que vous attendez. –

+0

Les deux applications envoient des chaînes à un serveur avec succès. J'attends la fin de RIOSend, j'ai simplement omis le code qui n'est pas lié à la création des sockets, car ce qui m'intéresse c'est la vitesse de RIOSend par lui-même. Mon application cliente va envoyer des requêtes de manière intensive, donc je considère toujours RIO. Suggérez-vous de tester l'heure d'exécution non pas d'une seule demande d'envoi, mais d'une grande quantité de demandes différentes? – Sergey

Répondre

0

RioSend() envoie pour de vrai. send() enregistre le tampon dans le tampon tx du socket.

+0

Dans ce cas. ['RioSend()'] (https://msdn.microsoft.com/fr-fr/library/windows/desktop/hh437213%28v=vs.85%29.aspx) a plusieurs comportements possibles en général. – EJP

+0

au meilleur de ma connaissance, avec Nagle désactivé, sans drapeau _DEFER, RioSend() irait au nic et initierait le DMA. –