Как увеличить пропускную способность UDPClient
Я смотрю на производительность.NET Core на Linux. В частности, чтобы убедиться, какие ограничения могут быть из инструментов, доступных в самой структуре.
Я попал в коробку с ~ 50000 pps. Похоже, что до сих пор UDPClient смог достичь ~ 20 000 pps, прежде чем выпадет достаточное количество пакетов. При использовании другого инструмента (syslog-ng) наблюдается редкая / низкая скорость потери пакетов.
Если я собираюсь обрабатывать до 50 Кбит / с, сможет ли UdpClient справиться с этим с помощью правильной настройки?
using (UdpClient udpListener = new UdpClient(_sysLogPort))
{
udpListener.Client.ReceiveBufferSize = _bufferSize;
while (!_cts.IsCancellationRequested)
{
try
{
UdpReceiveResult result = await udpListener.ReceiveAsync();
}
catch (Exception ex)
{
}
}
}
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) {}
}
}
}
}
}