Синхронизация Vs. Производительность асинхронных сокетов в .NET - PullRequest
10 голосов
/ 25 марта 2010

Все, что я читал о сокетах в .NET, говорит о том, что асинхронный шаблон обеспечивает лучшую производительность (особенно с новым SocketAsyncEventArgs, который экономит на распределении).

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

Но в моем приложении я являюсь клиентом, и мне просто нужно прослушать, как один сервер отправляет рыночные тиковые данные по одному TCP-соединению. Прямо сейчас я создаю отдельный поток, устанавливаю приоритет Highest и вызываю Socket.Receive () с ним. Мой поток блокирует этот вызов и просыпается при поступлении новых данных.

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

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

  2. Мне все равно придется отправлять все через один поток в какой-то момент. Скажем, я получаю одновременно N обратных вызовов в N различных потоках потоков, уведомляя меня о появлении новых данных. N-байтовые массивы, которые они доставляют, не могут быть обработаны в потоках пула потоков, потому что нет гарантии, что они представляют N уникальных сообщений рыночных данных, потому что TCP основан на потоке. В любом случае мне придется блокировать и помещать байты в массив и сигнализировать другому потоку, который может обрабатывать то, что находится в массиве. Так что я не уверен, что, имея N потоков пула, покупает меня.

Я думаю об этом неправильно? Есть ли причина использовать шаблон Async в моем конкретном случае, когда один клиент подключен к одному серверу?

UPDATE:

Так что я думаю, что неправильно понял схему асинхронности в (2) выше. Я получил бы обратный вызов в одном рабочем потоке, когда были доступны данные. Затем я начинаю другой асинхронный прием и получаю еще один обратный вызов и т. Д. Я не получу N обратных вызовов одновременно.

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

Ответы [ 3 ]

5 голосов
/ 25 марта 2010

Самой медленной частью вашего приложения будет сетевое взаимодействие. Весьма вероятно, что вы почти ничего не измените в производительности для одного потока, одного клиента подключения, настроив подобные вещи. Само сетевое взаимодействие затмит все другие вклады во время обработки или переключения контекста.

Скажите, что я получаю N обратных вызовов почти в то же время на N разные Threadpool темы, уведомляющие меня, что есть новые данные.

Почему это произойдет? Если у вас есть один сокет, вы Begin выполняете на нем операцию для получения данных, и вы получите ровно один обратный вызов, когда это будет сделано. Затем вы решаете, делать ли другую операцию. Похоже, вы слишком усложняете это, хотя, возможно, я упрощаю это в отношении того, что вы пытаетесь сделать.

В заключение я бы сказал: выберите простейшую модель программирования, которая дает вам то, что вы хотите; Учитывая варианты, доступные в вашем сценарии, они вряд ли окажут какое-либо заметное влияние на производительность, какой бы вы ни выбрали. С моделью блокировки вы «тратите» поток, который может выполнять какую-то реальную работу, но эй ... может быть, у вас нет реальной работы для этого.

3 голосов
/ 25 марта 2010

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

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

2 голосов
/ 25 марта 2010

"Этот класс был специально разработан для сетевых серверных приложений, требующих высокой производительности. "

Как я понимаю, вы клиент здесь, имея только одиночное соединение.
Данные по этому соединению поступают в порядке, потребляемом одним потоком.

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


Вам на самом деле не нужно ускорять это, вы, вероятно, не можете.

То, что вы можете сделать, - это отправить рабочие единицы другим потокам после того, как вы получите их. Для этого вам не нужен SocketAsyncEventArgs. Это может ускорить процесс.

Как всегда, измерить и измерить.
Кроме того, только то, что вы можете, это не значит, что вы должны.
Если производительности достаточно в обозримом будущем, зачем все усложнять?

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