如何增加 UDPClient 吞吐量
How to increase UDPClient throughput
我正在研究 .NET Core 在 linux 机器上的性能。特别要确定框架本身可用的工具可能存在什么样的限制。
我一直在用 ~ 50,000 pps 击中盒子。到目前为止,似乎 ~ 20,000 pps 是 UDPClient 在相当多的数据包被丢弃之前能够实现的。使用另一个工具 (syslog-ng) 有 rare/low 丢包率。
如果我希望处理超过 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)
{
}
}
}
即使您的应用使用 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) {}
}
}
}
}
}
我正在研究 .NET Core 在 linux 机器上的性能。特别要确定框架本身可用的工具可能存在什么样的限制。
我一直在用 ~ 50,000 pps 击中盒子。到目前为止,似乎 ~ 20,000 pps 是 UDPClient 在相当多的数据包被丢弃之前能够实现的。使用另一个工具 (syslog-ng) 有 rare/low 丢包率。
如果我希望处理超过 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)
{
}
}
}
即使您的应用使用 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) {}
}
}
}
}
}