Я - разработчик бэкэнда на C++. Я разрабатываю серверную часть для игры в реальном времени. Итак, архитектура приложения выглядит так:Как выбрать правильное количество потоков для многопоточного приложения C++?
1) У меня есть класс Client, который обрабатывает запросы от игрового клиента. Примеры запросов: войдите в систему, купите что-нибудь в магазине (внутренний магазин игры) или сделайте кое-что. Также этот клиент обрабатывает пользовательские события ввода от игрового клиента (часто это события, которые отправляются десять раз подряд с игрового клиента на сервер, когда игрок играет в геймплей).
2) У меня есть пул потоков. Когда игровой клиент подключается к серверу, я создаю экземпляр клиента и привязываю его к одному из потоков из пула. Итак, у нас есть отношения друг с другом: одна тема - много клиентов. Round-robin используется для выбора нити для привязки.
3) Я использую Libev для управления всеми событиями внутри сервера. Это означает, что когда экземпляр клиента получает некоторые данные от игрового клиента через сеть или обрабатывает какой-либо запрос или пытается отправить некоторые данные через сеть игровому клиенту, он блокирует поток hi. Пока он делает некоторые вещи, другие Клиенты, которые разделяют один и тот же поток, будут заблокированы.
Итак, пул потоков является узким местом для применения. Чтобы увеличить число одновременных игроков на сервере, кто будет играть без задержек, мне нужно увеличить количество потоков в пуле потоков.
Теперь приложение работает на сервере с 24 логическими процессорами (cat /proc/cpuinfo
). И я установил размер пула потоков до 24 (1 процессор - 1 поток). Это означает, что с текущими онлайн-участниками 2000 каждый поток обслуживает около 84 экземпляров клиента. top
говорят, что процессоры использовали менее 10 процентов.
Теперь вопрос. Если я увеличиваю количество потоков в пуле потоков, это увеличивает или уменьшает производительность сервера (накладные расходы на переключение контекста и заблокированные клиенты в потоке)?
UPD 1) Сервер имеет асинхронной IO (libev + Epoll), поэтому, когда я сказал, что клиент заблокирован, когда отправлять и получать данные, которые я имею в виду, справляясь в буфер. 2) Сервер также имеет фоновые потоки для медленных задач: операции с базами данных, жесткие расчетные операции, ...
Как правило: количество бегущих потоков должно быть примерно равно числу ядер ЦП. –
Хорошо, но как насчет ситуации, когда 10 потоков простаивают и ждут некоторых событий и 14 потоков перегружены. Я думаю, что если у сервера всего 10% нагрузки, я могу увеличить количество потоков, потому что некоторые из них спят. –
«пул потоков является узким местом для применения» - это смелое утверждение, что заставляет вас так думать? Во всяком случае, вы спрашиваете, что такое производительность вашей системы. Первое, что вам нужно сделать, это настроить способы измерения. Во-первых, ваш вопрос становится устаревшим. Во-вторых, вы можете измерить свои попытки улучшить производительность. –