2017-08-08 56 views
0

我正在研究Linux核心在Linux机器上的性能。具体确定框架本身可用的工具有哪些限制。如何增加UDPClient吞吐量

我一直在约50,000箱/每箱。到目前为止,看起来〜20,000 pps是UDPClient在一小部分数据包丢失之前能够实现的。使用另一种工具(syslog-ng)会出现罕见/低丢包率。

如果我想要处理高达50K pps,UdpClient能够通过适当的调整来处理这个问题吗?

using (UdpClient udpListener = new UdpClient(_sysLogPort)) 
{ 
    udpListener.Client.ReceiveBufferSize = _bufferSize; 

    while (!_cts.IsCancellationRequested) 
    { 
     try 
     { 
      UdpReceiveResult result = await udpListener.ReceiveAsync(); 
     } 
     catch (Exception ex) 
     { 

     } 
    } 
} 
+0

您的主要武器是通过SO_RCVBUFSIZ来增加套接字接收缓冲区的大小,但是会在您使用的API中显示。 – EJP

+0

@EJP我相信ReceiveBufferSize属性是处理这个问题的部分(我可能是错的),但是当前发送的数据包非常小,缓冲区限制远大于当前发送的数据包。这感觉就像我可能对UdpClient缺少一些调整,因为syslog-ng能够以很少的溢出处理这个流量 –

+0

你用来发送数据包到这个程序的包大小是多少?你使用哪个工具发送这些数据包?你使用哪种处理器类型?你能否确认你使用的是回送接口(即发送者和你的程序在同一台Linux主机上)?您在Linux机器上使用的是哪个版本的dotnet:1.0.4,更旧,更新? –

回答

1

即使你的应用程序启动与udpListener.ReceiveAsync();一个新的线程,它尝试接收新的数据包之前,等待其结束。因此,一次只有一个线程处理新收到的UDP数据包,以创建UdpReceiveResult类型的对象。因此,它与单线程应用程序非常相似:您可以使用而不是利用此机会在多核系统上运行。

您可以通过以下方式编写程序,获得更好的费率(显然取决于您的硬件)。在这个例子中,有5个并行运行的线程池可以同时创建UdpReceiveResult的多个实例。即使数据包一次由内核处理,创建UdpReceiveResult实例的用户级进程也是通过这种编程方式并行完成的。

// example of multithreaded UdpClient with .NET core on Linux 
// works on Linux OpenSuSE LEAP 42.1 with .NET Command Line Tools (1.0.4) 
// passed tests with "time nping --udp -p 5555 --rate 2000000 -c 52000 -H localhost > /dev/null" 

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Net; 
using System.Net.Sockets; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows; 

namespace hwapp { 
    class Program { 
    // listen to port 5555 
    UdpClient udpListener = new UdpClient(5555); 

    static void Main(string[] args) { 
     Program p = new Program(); 
     // launch 5 threads 
     Task t0 = p.listen("thread 0"); 
     Task t1 = p.listen("thread 1"); 
     Task t2 = p.listen("thread 2"); 
     Task t3 = p.listen("thread 3"); 
     Task t4 = p.listen("thread 4"); 
     t0.Wait(); t1.Wait(); t2.Wait(); t3.Wait(); t4.Wait(); 
    } 

    public async Task listen(String s) { 
     Console.WriteLine("running " + s); 
     using (udpListener) { 
     udpListener.Client.ReceiveBufferSize = 2000; 
     int n = 0; 
     while (n < 10000) { 
      n = n + 1; 
      try { 
      UdpReceiveResult result = udpListener.Receive(); 
      } catch (Exception ex) {} 
     } 
     } 
    } 
    } 
}