Высокопроизводительный UDP-сервис .NET - PullRequest
2 голосов
/ 10 февраля 2011

Я пытаюсь выжать как можно больше из моего сокета сбора данных UDP, используя следующий код:

public void Start()
{

    if (socket == null) Open();
    this.stats.PositionServerStarted = DateTime.Now;
    this.state = SocketWorkerState.Running;
    AsyncBeginReceive();
}

private void AsyncBeginReceive()
{
    DataPacket dataPacket = new DataPacket(socket, this.settings.IPAddress,
        this.settings.Port, SocketWorker.MaxDataRead);
    Interlocked.Increment(ref stats.ProcessingThreads);
    socket.BeginReceiveFrom(dataPacket.BytePacket, 0, 
        SocketWorker.MaxDataRead, SocketFlags.None, 
        ref dataPacket.RemoteEndPoint, new AsyncCallback(AsyncEndReceive), 
        dataPacket);
}

private void AsyncEndReceive(IAsyncResult ar)
{
    DataPacket dataPacket= null;
    AsyncBeginReceive();
    dataPacket = (DataPacket)ar.AsyncState;
    dataPacket.EnteredQueue = DateTime.Now;
    dataPacket.DataLength= dataPacket.SourceSocket.EndReceiveFrom(ar, 
        ref dataPacket.RemoteEndPoint);
    Interlocked.Decrement(ref stats.ProcessingThreads);
    Interlocked.Increment(ref this.stats.PacketsQueued);
    ThreadPool.QueueUserWorkItem(new WaitCallback(OnPacketArrived), 
        dataPacket);
    Interlocked.Decrement(ref this.stats.PacketsQueued);
}

private void OnPacketArrived(object packet)
{
    //go ahead and process the packet
}

У кого-нибудь есть идеи, как это улучшить? Звонит ли AsyncBeginReceive() из AsyncEndReceive() лучшей практикой?

Я настроил пул потоков

ThreadPool.SetMinThreads(20,20);
ThreadPool.SetMaxThreads(250, 250);

Но, если честно, это не сильно влияет на производительность.

Ответы [ 3 ]

1 голос
/ 10 февраля 2011

Лично я бы отправил несколько recvs при запуске, то есть вызов AsyncBeginReceive() настраиваемое количество раз.Таким образом, вам не нужно ждать завершения одного recv, прежде чем начнется следующий.В неуправляемых терминах, как правило, хорошая идея всегда иметь ожидающее асинхронное чтение, чтобы подсистема ввода-вывода могла читать прямо в ваши буферы, если это возможно - это может или не может привести к повышению производительности, но вполне вероятно, что это приведет к меньшему количеству потерянных дейтаграмм.,

Возможно, вы также захотите увеличить размер буфера recv сокета, так как это также поможет предотвратить потерю дейтаграмм.

Я сомневаюсь, что вам придется настроить параметры пула потоков.В неуправляемом коде вы можете работать с полностью загруженным сетевым каналом с <или около того потоками, используя асинхронный ввод-вывод;что 250 из вас далеко от цели. </p>

0 голосов
/ 10 февраля 2011

Я не думаю, что async - это хороший способ достичь высокой производительности. Читайте вручную и запрашивайте большие порции данных в каждом проходе. Если у вас небольшое количество одновременных подключений, вы можете даже выделить им потоки, чтобы сокеты были полностью сосредоточены. Асинхронные операции требуют много времени по сравнению с прямым доступом.

Если вам нужна действительно высокая пропускная способность, рассмотрите возможность установки приоритета потока. Также обратите внимание, что приоритет .Net является только относительным, поэтому вы можете установить приоритет процесса .

Параметры оптимизации в свойствах проекта могут оказать заметное влияние на производительность, если вы смотрите на высокую пропускную способность.

0 голосов
/ 10 февраля 2011

Оптимизируйте, только если то, что у вас есть, работает недостаточно хорошо, и если вам нужно оптимизировать, делайте это на основе метрик - попробуйте разные подходы и используйте то, что работает лучше всего.

Тем не менее, я не уверен, что этот подход более эффективен, чем просто наличие n + 1 потоков в цикле, который блокирует ReceiveFrom, а затем завершает обработку каждого пакета синхронно,избегая использования как асинхронного ввода / вывода, так и организации потоков между потоками.Установите n на количество устройств с узкими местами (обычно ядра процессора, но шпиндели могут быть и вашим ограничивающим ресурсом, если вы сильно связаны с вводом / выводом, или, возможно, и тем, и другим);Часть «+ 1» предназначена только для того, чтобы избежать простоя устройства под нагрузкой, когда поток делает что-то еще.

У меня были некоторые очень болезненные ситуации с асинхронным I на основе ThreadPool и BeginXxx./ O в .Net (как в полной, так и в компактной среде), поэтому я вообще не рекомендую их использовать.С другой стороны, большая часть боли (по крайней мере, от асинхронного ввода-вывода) могла быть связана с враждебным кодом других;ThreadPool просто не надежен на компактной основе.: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...