Производительность ReceiveAsync против BeginReceive - PullRequest
7 голосов
/ 29 марта 2012

В настоящее время я программирую клиентское приложение, и мне интересно, должен ли я использовать метод Socket класса 'ReceiveAsync или BeginReceive.До сих пор я использовал последний, однако обнаружил, что он, похоже, сильно нагружает процессор.Вот как выглядит мой цикл приема:

private void socket_ReceiveCallback(IAsyncResult result_)
{
    // does nothing else at the moment
    socket.EndReceive(result_);
    byte[] buffer = (byte[])result_.AsyncState;

    // receive new packet
    byte[] newBuffer = new byte[1024];
    socket.BeginReceive(newBuffer, 0, newBuffer.Length, SocketFlags.None, 
                        socket_ReceiveFallback, newBuffer);
}

Теперь мне стало интересно, не делаю ли я здесь что-то не так, поскольку другие приложения, которые обмениваются данными, почти не нагружают процессор.А также мне интересно, было бы мне лучше использовать SocketAsyncEventArgs и ReceiveAsync.

Итак, вот мои вопросы:

Почему мой цикл так сильно нагружает процессор?Должен ли я использовать SocketAsyncEventArgs и ReceiveAsync вместо BeginReceive?

Ответы [ 3 ]

6 голосов
/ 29 марта 2012

Я сравнивал синхронный и асинхронный сокеты для локального петлевого соединения. Мои результаты заключались в том, что асинхронная версия была примерно на 30% медленнее. Это было удивительно для меня, учитывая, что асинхронный ввод-вывод сейчас в моде. Неважно, сколько потоков я использовал. Я мог бы использовать 128 потоков, но синхронный ввод-вывод был быстрее.

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

Таким образом, вы можете просто переключиться на синхронный ввод-вывод, если не ожидаете сотни одновременных подключений.

1 голос
/ 02 ноября 2018

BeginReceive и EndReceive являются остатками старого устаревшего асинхронного шаблона, который использовался до введения современных ключевых слов async и await в C # 5.

Таким образом, вы должны использовать ReceiveAsync вместо BeginReceive и EndReceive для асинхронного программирования.

Для действительно высокопроизводительных сценариев вы должны использовать SocketAsyncEventArgs. Это было разработано для высокой производительности и используется веб-сервером Kestrel.

Из раздела замечаний для документации SocketAsyncEventArgs

Класс SocketAsyncEventArgs является частью набора улучшений класса System.Net.Sockets.Socket, которые предоставляют альтернативный асинхронный шаблон, который может использоваться специализированными высокопроизводительными приложениями сокетов. Этот класс был специально разработан для приложений сетевого сервера, которые требуют высокой производительности. Приложение может использовать расширенный асинхронный шаблон исключительно или только в целевых горячих областях (например, при получении больших объемов данных).

Основной особенностью этих улучшений является предотвращение повторного выделения и синхронизации объектов во время асинхронного ввода-вывода с большим объемом. Шаблон проектирования Begin / End, в настоящее время реализуемый классом System.Net.Sockets.Socket, требует, чтобы объект System.IAsyncResult был выделен для каждой асинхронной операции сокета.

В новых усовершенствованиях класса System.Net.Sockets.Socket асинхронные операции с сокетами описываются повторно используемыми объектами SocketAsyncEventArgs, размещенными и поддерживаемыми приложением. Высокопроизводительные приложения сокетов лучше всего знают количество операций с сокетами, которые необходимо поддерживать. Приложение может создать столько объектов SocketAsyncEventArgs, сколько ему нужно. Например, если серверное приложение должно иметь 15 операций приема сокетов, все время ожидающих обработки, для поддержки скорости входящих клиентских соединений, оно может выделить для этой цели 15 повторно используемых объектов SocketAsyncEventArgs.

1 голос
/ 29 марта 2012

ответьте, что вам нужно профилировать вашу заявку. Что мне интересно, так это

  • почему я не вижу EndReceive
  • почему вы вообще не используете полученный буфер и
  • почему вы снова и снова выделяете новые буферы - это единственная операция, которая требует любых ресурсов (ЦП / память)

Посмотрите на это: http://msdn.microsoft.com/de-de/library/dxkwh6zw.aspx

...