2017-08-08 140 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) {} 
     } 
     } 
    } 
    } 
}