Многопоточные и блокирующие розетки - PullRequest
0 голосов
/ 22 февраля 2011

Я пишу TCP-сервер на Windows Server 2k8.Эти серверы получают данные, анализируют их и затем помещают в базу данных.Сейчас я делаю некоторые тесты, но результаты меня удивляют.

Приложение написано на C ++ и использует напрямую Winsocks и Windows API.Он создает поток для каждого клиентского соединения.Для каждого клиента он читает и анализирует данные, а затем вставляет их в базу данных.

Клиенты всегда подключаются одновременно:время от времени около 5 (я контролирую этот параметр) клиентов будут одновременно подключаться и подавать данные серверу.

Я синхронизировал этапы чтения и синтаксического анализа, а также связанные с базой данных этапы каждого из них.thread.

Первый этап (чтение и анализ) имеет любопытное поведение.Количество времени, которое занимает каждый поток, примерно равно каждому потоку, но также пропорционально количеству соединяющихся потоков.Сервер не истощен ЦП: у него 8 ядер, и к нему всегда подключено менее 8 потоков.

Например, при трех одновременных потоках 100 тыс. Строк (для каждого потока) будут считываться и анализироваться примерно за 4,5 с.Но с 5 потоками это займет в среднем 9,1 с!

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

Если это так, я был бы рад, если бы кто-то указал мне хорошие ресурсы для понимания неблокирующих сокетов в Windows.

Редактировать :

Каждый клиентский поток читает строку (т. Е. Все символы до '\ n') из сокета, затем анализирует ее, затем снова читает, до тех пор, пока анализ не завершится илитерминатор найденМоя подпрограмма readline основана на этом:

http://www.cis.temple.edu/~ingargio/cis307/readings/snaderlib/readline.c

Со статическими переменными, объявленными как __declspec (thread).

Синтаксический анализ, исходя из не сетевой версии,эффективен (около 2 с для 100 тыс. строк).Поэтому я предполагаю, что проблема в многопоточной / сетевой версии.

Ответы [ 5 ]

4 голосов
/ 22 февраля 2011

Если ваши строки имеют длину ~ 120 - 150 символов, вы фактически насыщаете сеть!

Нет проблем с розетками. Простая передача 3-х строк по 100 тыс., Каждая по 150 байт, по линии со скоростью 100 Мбит / с (1 занимает 10 байт / байт для учета заголовков) займет ... 4,5 с! Нет проблем с розетками, блокировками или иным образом. Вы просто достигли предела того, сколько данных вы можете передать.

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

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

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

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

В вашем случае это не проблема, поскольку в каждом потоке имеется только одно подключение, поэтомуНет проблем, если ваш поток ожидает ввода.

Что приводит к вашим первоначальным вопросам о том, почему все замедляется, когда у вас есть больше соединений.Без дополнительной информации наиболее вероятным виновником является то, что вы ограничены в сети: то есть ваша сеть не может достаточно быстро передавать данные с вашего сервера.

Если вас интересуют неблокирующие сокеты в Windows, выполните поиск в MSDN для OVERLAPPED.API-интерфейсы

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

Помимо блокирования и неблокирования, вы также можете изучить Microsoft overlapped I/O.Google - ваш друг, но используйте overlapped I/O как часть вашего поискового запроса.

Общий фон по теме можно найти здесь Ввод / вывод с перекрытием сокетов и режим блокировки / неблокирования .В этой статье проводится различие между двумя концепциями блокировки / неблокирования и перекрывающегося ввода-вывода.

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

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

MSDN довольно неплохо справляется с документированием режимов блокировки / неблокирования, а также overlapped I/O API Перекрывающиеся объекты ввода-вывода и события .

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

Следует иметь в виду, что, хотя у вас есть один поток на клиента, Windows не будет автоматически гарантировать, что все они работают на разных ядрах. Если некоторые из них работают на одном и том же ядре, возможно (хотя и маловероятно), чтобы ваш сервер находился в состоянии нехватки ресурсов процессора, при этом некоторые ядра загружены на 100%, а другие бездействуют. Просто нет никаких гарантий относительно того, как ОС распределяет нагрузку (в случае по умолчанию).

Чтобы явно назначить потоки определенным ядрам, вы можете использовать SetThreadAffinityMask . Возможно, стоит или не стоит потренироваться, чтобы посмотреть, поможет ли это.

С другой стороны, это может не иметь к этому никакого отношения. YMMV.

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