上限UDP性能Windows Server 2008上(Upper limit to UDP per

2019-07-29 08:06发布

它看起来像从我的测试中,我打我的10GB网络上的性能瓶颈。 我似乎无法读取超过每秒180-200k包。 纵观性能监视器或任务管理器,我可以第二,如果不是更获得高达一百万包/。 测试1插槽或10或100,似乎并没有改变200-300k分组的第二此限制。 我摆弄RSS之类没有成功。 单播组播VS似乎并不重要,重叠I / O VS同步不有所作为无论是。 数据包的大小并不重要任。 那里只是似乎是一个硬性限制数据包窗口可以从网卡到缓冲区拷贝的数量。 这是戴尔R410。 有任何想法吗?

#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;
}

我使用的Iperf作为发送和接收的比较对发送的数据量的数据量:iperf.exe -c 10.20.16.90 -u -P 10 -B 10.20.16.51 -b十亿-p 12400 -l 1000

编辑:做的iperf到的iperf性能更接近180K左右不丢弃(8MB客户端缓冲液)。 如果我做TCP我可以做20万包/秒。 这里是有趣的,但 - 我可以做多个TCP连接远远超过20万,但多个UDP连接不增加总的(我测试多iperfs UDP性能,因为多线程单一的iperf似乎不工作)。 所有的硬件加速的驱动程序调整上..好像UDP表现简直欠佳?

Answer 1:

我一直在做类似的硬件部分UDP测试,我调查的性能提升,可以使用该可以了Winsock的注册I / O网络的扩展,RIO ,在Windows 8服务器。 为此,我已经在Windows Server 2008 R2中和Windows Server 8上运行测试。

我还没有去的地步,我已经开始与我们的10Gb卡测试点(他们刚刚到达),但我的早期测试,用来运行它们的示例程序的结果可以发现这里在我的博客 。

有一两件事,我可能会建议是,用一个简单的测试一样,你表现出那里的正在做的,你会发现每个数据报的工作很少是老式的,同步I / O,比IOCP设计得更快。 虽然IOCP设计超前的步骤每上升数据报的工作量,你可以充分利用多线程。

此外,在您的测试机有线背靠背(即没有开关)或他们通过一个开关运行; 如果是的话,可能问题会下降到您的交换机,而不是你的测试机器的性能? 如果您使用的是开关,或有多个网卡的服务器,你可以对服务器运行多个客户端,可以在问题是客户端,而不是在服务器上?

什么CPU使用率是你看到的发送和接收的机器? 你看用Process Explorer的机器的cpu使用率? 这比任务管理器更准确。 其中CPU是处理网卡中断,您可以通过结合这些到另一个CPU改善的事情? 或改变你的测试程序到另一个CPU上运行的亲和力? 是您的IOCP以身作则推广其在多个NUMA节点线程或者是你锁定他们都一个节点?

我希望能得到下周运行一些测试,当我这样做会更新我的答案。

编辑:对我来说,这个问题是由于一个事实,即网卡驱动程序启用了“流量控制”,这引起了发件人在接收器的速度运行。 这有一些不受欢迎的“非分页池”的使用特性和关闭流量控制可以让你看到发送者可以多快(在发送者和接收者之间的网络利用率的差别清晰地显示多少数据丢失)。 见我的博客张贴在这里了解更多详情。



文章来源: Upper limit to UDP performance on windows server 2008