Сколько ресурсов потребляют спящие и ожидающие потоки

StackOverflow https://stackoverflow.com/questions/100707

Вопрос

Мне интересно, насколько дорого стоит иметь много потоков в состоянии ожидания в Java 1.6 x64.

Если быть более конкретным, я пишу приложение, которое работает на многих компьютерах и отправляет/получает данные с одного на другой.Мне удобнее иметь отдельный поток для каждой подключенной машины и задачи, например: 1) отправка данных, 2) получение данных, 3) восстановление соединения при его разрыве.Итак, учитывая, что в кластере N узлов, каждая машина будет иметь по 3 потока для каждого из N-1 соседей.Обычно имеется 12 машин, что соответствует 33 коммуникационным потокам.

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

Так есть ли какое-либо существенное влияние на производительность при наличии большого количества спящих потоков?

Это было полезно?

Решение

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

Я сам был в такой ситуации, и когда количество соединений превышало 500 соединений (около тысячи потоков), вы склонны сталкиваться со многими случаями, когда вы получаете OutOfMemoryError, поскольку использование пространства стека потоков превышает максимальный объем память для одного процесса.По крайней мере, в нашем случае, который был в мире Java в 32-битной Windows.Я думаю, вы можете что-то настроить и пойти немного дальше, но, в конце концов, это просто не очень масштабируемо, поскольку вы тратите много памяти.

Если вам нужно большое количество соединений, Java NIO (новый ввод-вывод или что-то еще) — это то, что вам нужно, что позволяет обрабатывать множество соединений в одном потоке.

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

Другие советы

У нас была почти такая же проблема до того, как мы перешли на NIO, поэтому я поддержу рекомендацию Лидмана использовать эту структуру.Вы сможете найти руководство, но если вам нужны подробности, я могу порекомендовать Ява НИО Рон Хитченс.

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

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

Множество потоков соответствует большому количеству места в стеке, которое съедает вашу память - проверьте настройки -Xss, сколько именно, а затем посчитайте.

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

Я не уверен, что в этой модели можно легко избежать наличия одного потока на каждый сокет прослушивания (хотя я очень мало знаю о NIO, что может решить даже эту проблему), но взгляните на java.util.concurrent.Executor интерфейс и его реализующие классы, чтобы обеспечить достойный способ избежать слишком большого количества дополнительных потоков.Действительно, ThreadPoolExecutor Это также может быть хорошим способом управления потоками прослушивания, чтобы вы не тратили слишком много времени на создание и уничтожение потоков без необходимости.

Судя по тестам, которые я провел на C, Lua и Python, вы можете создать свою собственную функцию сна или ожидания с помощью очень небольшого количества строк кода, чтобы создать простой облегченный цикл.Используйте локальную переменную со временем в будущем, которого вы хотите достичь, а затем проверьте текущую метку времени в цикле while.Если вы находитесь в области, где вы работаете с частотой кадров, заставьте функцию ожидания запускаться один раз за кадр, чтобы сэкономить ресурсы.Чем больше точности вам требуется, рассмотрите возможность использования часов вместо отметки времени, поскольку отметка времени ограничена секундами.Чем больше строк кода вы добавляете в функцию ожидания, тем менее точной она становится и тем больше ресурсов она потребляет, хотя все, что меньше 10 строк, должно быть достаточно быстрым.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top