Сколько потоков-это слишком много? [закрытый]


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

мой вопрос в том, что такое хорошая точка отсечки для таких потоков ввода/вывода? Я знаю, что это будет грубая оценка, но мы говорим о сотнях? тысячи?


EDIT:

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

12 263

12 ответов:

некоторые люди сказали бы, что два темы-это слишком много - я не совсем в этом лагере :-)

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

Если ваш поток использования пиков на 3, то 100 слишком много. Если он остается на 100 в течение большей части дня, поднять его до 200 и посмотреть, что происходит.

вы может на самом деле ваш код сам контролирует использование и настраивает конфигурацию для следующего запуска, но это, вероятно, излишне.


для уточнения и доработки:

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

Я написал код пула соединений с потоками и базами данных, и у них есть следующие функции (которые, по моему мнению, необходимы для производительности):

  • минимальное количество активных потоков.
  • максимальное количество потоков.
  • завершение работы потоков, которые не использовались в течение некоторого времени.

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

вы должны сбалансировать использование ресурсов, имеющих неиспользуемые потоки (A) против использования ресурсов, не имеющих достаточного количества потоков для выполнения работы (B).

(A) обычно используется память (стеки и т. д.), поскольку поток, не выполняющий никакой работы, не будет использовать большую часть ЦП. (B) как правило, будет задержка в обработке запросов по мере их поступления, поскольку вам нужно ждать, пока поток станет доступным.

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

первое-это количество доступных подключений к БД. Это может быть жесткий предел, если вы не можете увеличить его на СУБД-я собираюсь предположить, что ваша СУБД может принимать неограниченное количество соединений в этом случае (хотя в идеале вы должны также измерять это).

затем, количество потоков, которые вы должны зависеть от вашего использования. Минимум, который вы должны иметь, - это минимальное число, которое у вас когда-либо было + A%, с абсолютным минимумом (например, и сделать его настраиваемым так же, как A) 5.

максимальное количество потоков должно быть вашим историческим максимум + Б%.

вы также должны следить за изменениями в поведении. Если по какой-то причине ваше использование идет на 100% от доступного в течение значительного времени (чтобы это повлияло на производительность клиентов), вы должны поднять максимально допустимый уровень, пока он снова не станет на B% выше.


в ответ на "что именно я должен измерить?"вопрос:

то, что вы должны измерить конкретно, это максимальное количество потоков в параллельном режиме используйте (например, ожидание возврата от вызова DB) под нагрузкой. Затем добавьте коэффициент безопасности 10% для пример (подчеркнуто, поскольку другие плакаты, похоже, берут мои примеры в качестве фиксированных рекомендаций).

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

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

  1. размер стека потоков: в Linux размер стека потоков по умолчанию составляет 8 МБ (вы можете использовать ulimit-a, чтобы узнать это).
  2. максимальная Виртуальная память, которую поддерживает данный вариант ОС. Ядра Linux 2.4 поддерживает адресное пространство памяти 2 ГБ. с ядром 2.6, я немного больше (3 ГБ )
  3. [1] показывает вычисления для максимального количества потоков на заданную максимальную поддерживаемую виртуальную машину. Для 2.4 получается около 255 потоков. для 2.6 число немного больше.
  4. какой у вас планировщик ядра kindda . Сравнивая планировщик ядра Linux 2.4 с 2.6 , более поздний дает вам o(1) планирование без зависимости от количества задач, существующих в системе, в то время как первый из них больше O (n). Таким образом, возможности SMP расписания ядра также играют хорошую роль в максимальном количестве устойчивых потоков в системе.

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

обратите внимание , что можно создать тысячи потоков по своему желанию, но когда Linux заканчивается VM, он просто случайно начинает убивать процессы (таким образом, потоки). Это делается для того, чтобы профиль утилиты не был превышен. (Функция полезности говорит о общесистемной полезности для заданного количества ресурсов. С постоянными ресурсами в этом случае циклы процессора и памяти, кривая полезности выравнивается с все большим и большим количеством задач ).

Я уверен планировщик ядра windows также делает что-то подобное, чтобы справиться с чрезмерным использованием ресурсов

[1] http://adywicaksono.wordpress.com/2007/07/10/i-can-not-create-more-than-255-threads-on-linux-what-is-the-solutions/

Если ваши потоки выполняют какую-либо ресурсоемкую работу (CPU/Disk), то вы редко увидите преимущества за пределами одного или двух, и слишком много будет убивать производительность очень быстро.

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

A хорошим решением является размещение запросов в пуле, которые затем отправляются в рабочие потоки из пула потоков (и да, предотвращение непрерывного создания/уничтожения потока-отличный первый шаг).

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

одна вещь, которую вы должны иметь в виду, что python (по крайней мере, версия на основе C) использует то, что называется a глобальная переводчик замок это может иметь огромное влияние на производительность на многоядерных машинах.

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

Как правильно сказал Пакс,мера, не думаю. Это то, что я сделал для DNSwitness и результаты были удивительными: идеальное количество потоков было намного выше, чем я думал, что-то вроде 15 000 потоков, чтобы получить самые быстрые результаты.

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

полные меры (только на французском языке) в Combien de fils d'exécution ?.

Я написал несколько сильно многопоточных приложений. Обычно я разрешаю указывать количество потенциальных потоков в файле конфигурации. Когда я настроился для конкретных клиентов, я установил достаточно высокое число, чтобы мое использование всех ядер процессора было довольно высоким, но не настолько высоким, чтобы я столкнулся с проблемами памяти (это были 32-разрядные операционные системы в то время).

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

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

ответ "большого железа", как правило, один поток на ограниченный ресурс-процессор (CPU bound), arm (I/O bound) и т. д.-Но это работает только в том случае, если вы можете направить работу в правильный поток для доступа к ресурсу.

Если это невозможно, считайте, что у вас есть взаимозаменяемые ресурсы (процессоры) и не взаимозаменяемые ресурсы (оружие). Для процессоров не критично назначать каждый поток определенному процессору (хотя это помогает с управлением кешем), но для arms, если вы не можете назначить нить к руке, вы попадаете в теорию очередей и какое оптимальное количество, чтобы держать руки занятыми. Обычно я думаю, что если вы не можете маршрутизировать запросы на основе используемой руки, то наличие 2-3 потоков на руку будет примерно правильным.

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

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

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

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

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

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

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

вы можете найти дополнительную информацию о том, как это должно работать здесь:http://en.wikipedia.org/wiki/Thread_pool_pattern

столько потоков, сколько ядер процессора - это то, что я слышал очень часто.