Верхний предел производительности UDP на Windows Server 2008
Похоже, что из моего тестирования я попал в стену производительности в моей сети 10 ГБ. Кажется, я не могу читать более 180-200k пакетов в секунду. Глядя на perfmon или диспетчер задач, я могу получать до миллиона пакетов в секунду, если не больше. Тестирование 1 сокета или 10 или 100, похоже, не изменяет этот предел в 200-300 тыс. Пакетов в секунду. Я безуспешно возился с RSS и тому подобным. Unicast против многоадресной рассылки, кажется, не имеет значения, перекрытие ввода-вывода против синхронного также не имеет значения. Размер пакета также не имеет значения. Кажется, существует жесткое ограничение на количество пакетов, которые окна могут копировать из буфера в ник. Это dell r410. Есть идеи?
<code>#include "stdafx.h" #include <WinSock2.h> #include <ws2ipdef.h> static inline void fillAddr(const char* const address, unsigned short port, sockaddr_in &addr) { memset( &addr, 0, sizeof( addr ) ); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr( address ); addr.sin_port = htons(port); } int _tmain(int argc, _TCHAR* argv[]) { #ifdef _WIN32 WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); #endif int error = 0; const char* sInterfaceIP = "10.20.16.90"; int nInterfacePort = 0; //Create socket SOCKET m_socketID = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); //Re use address struct sockaddr_in addr; fillAddr( "10.20.16.90", 12400, addr ); //"233.43.202.1" char one = 1; //error = setsockopt(m_socketID, SOL_SOCKET, SO_REUSEADDR , &one, sizeof(one)); if( error != 0 ) { fprintf( stderr, "%s: ERROR setsockopt returned %d.\n", __FUNCTION__, WSAGetLastError() ); } //Bind error = bind( m_socketID, reinterpret_cast<SOCKADDR*>( &addr ), sizeof( addr ) ); if( error == -1 ) { fprintf(stderr, "%s: ERROR %d binding to %s:%d\n", __FUNCTION__, WSAGetLastError(), sInterfaceIP, nInterfacePort); } //Join multicast group struct ip_mreq mreq; mreq.imr_multiaddr.s_addr = inet_addr("225.2.3.13");//( "233.43.202.1" ); mreq.imr_interface.s_addr = inet_addr("10.20.16.90"); //error = setsockopt( m_socketID, IPPROTO_IP, IP_ADD_MEMBERSHIP, reinterpret_cast<char*>( &mreq ), sizeof( mreq ) ); if (error == -1) { fprintf(stderr, "%s: ERROR %d trying to join group %s.\n", __FUNCTION__, WSAGetLastError(), "233.43.202.1" ); } int bufSize = 0, len = sizeof(bufSize), nBufferSize = 10*1024*1024;//8192*1024; //Resize the buffer getsockopt(m_socketID, SOL_SOCKET, SO_RCVBUF, (char*)&bufSize, &len ); fprintf(stderr, "getsockopt size before %d\n", bufSize ); fprintf(stderr, "setting buffer size %d\n", nBufferSize ); error = setsockopt(m_socketID, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<const char*>( &nBufferSize ), sizeof( nBufferSize ) ); if( error != 0 ) { fprintf(stderr, "%s: ERROR %d setting the receive buffer size to %d.\n", __FUNCTION__, WSAGetLastError(), nBufferSize ); } bufSize = 1234, len = sizeof(bufSize); getsockopt(m_socketID, SOL_SOCKET, SO_RCVBUF, (char*)&bufSize, &len ); fprintf(stderr, "getsockopt size after %d\n", bufSize ); //Non-blocking u_long op = 1; ioctlsocket( m_socketID, FIONBIO, &op ); //Create IOCP HANDLE iocp = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, NULL, 1 ); HANDLE iocp2 = CreateIoCompletionPort( (HANDLE)m_socketID, iocp, 5, 1 ); char buffer[2*1024]={0}; int r = 0; OVERLAPPED overlapped; memset(&overlapped, 0, sizeof(overlapped)); DWORD bytes = 0, flags = 0; // WSABUF buffers[1]; // // buffers[0].buf = buffer; // buffers[0].len = sizeof(buffer); // // while( (r = WSARecv( m_socketID, buffers, 1, &bytes, &flags, &overlapped, NULL )) != -121 ) //sleep(100000); while( (r = ReadFile( (HANDLE)m_socketID, buffer, sizeof(buffer), NULL, &overlapped )) != -121 ) { bytes = 0; ULONG_PTR key = 0; LPOVERLAPPED pOverlapped; if( GetQueuedCompletionStatus( iocp, &bytes, &key, &pOverlapped, INFINITE ) ) { static unsigned __int64 total = 0, printed = 0; total += bytes; if( total - printed > (1024*1024) ) { printf( "%I64dmb\r", printed/ (1024*1024) ); printed = total; } } } while( r = recv(m_socketID,buffer,sizeof(buffer),0) ) { static unsigned int total = 0, printed = 0; if( r > 0 ) { total += r; if( total - printed > (1024*1024) ) { printf( "%dmb\r", printed/ (1024*1024) ); printed = total; } } } return 0; } </code>
Я использую Iperf в качестве отправителя и сравниваю объем полученных данных с количеством отправленных данных: iperf.exe -c 10.20.16.90 -u -P 10 -B 10.20.16.51 -b 1000000000 -p 12400 -l 1000
редактировать: делать iperf для iperf производительность ближе к 180k или около того, не сбрасывая (8 МБ буфер на стороне клиента). Если я делаю tcp, я могу делать около 200 тыс. Пакетов в секунду. Вот что интересно, хотя - я могу сделать намного больше, чем 200 КБ с несколькими соединениями TCP, но несколько соединений UDP не увеличивают общее количество (я тестирую производительность UDP с несколькими iperfs, так как один iperf с несколькими потоками, кажется, не работает ). Все аппаратное ускорение настроено в драйверах. Кажется, производительность УДП просто ниже нормы?