Сколько streamов слишком много?

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

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


РЕДАКТИРОВАТЬ:

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

Некоторые люди сказали бы, что двух streamов слишком много – я не совсем в этом лагере 🙂

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

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

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


Для уточнения и уточнения:

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

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

  • минимальное количество активных streamов.
  • максимальное количество streamов.
  • отключив streamи, которые не использовались некоторое время.

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

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

(A) – это обычно использование памяти (стеки и т. Д.), Так как stream, не выполняющий работу, не будет использовать большую часть процессора. (B), как правило, является задержкой в ​​обработке запросов по мере их поступления, поскольку вам нужно ждать, пока stream станет доступным.

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

«Большой железный» ответ – это, как правило, один stream на один ограниченный ресурс – процессор (привязка к процессору), arm (привязка ввода / вывода) и т. Д. – но это работает только в том случае, если вы можете перенаправить работу на нужную нить для ресурса доступ к ним.

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

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

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

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

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

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

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

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

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

То, что я слышал очень часто, так много streamов, как ядра процессора.

  • Студия Android занимает слишком много памяти
  • Что более эффективно i ++ или ++ i?
  • Насколько дорогим является RTTI?
  • смешение cout и printf для более быстрого вывода
  • dbms_output.put_line
  • Какие счетчики perfmon полезны для выявления узких мест ASP.NET?
  • Эффективные C ++ строки (интернирование, веревки, копирование на запись и т. Д.)
  • Что быстрее: распределение стека или выделение кучи
  • StringBuilder / StringBuffer против оператора «+»
  • Каков самый быстрый способ обмена значениями в C?
  • Оптимизация кэширования файлов и HTTP2
  • Давайте будем гением компьютера.