Когда использовать шаблон разрушителя и когда локальное хранилище с кражей работы?

Правильно ли это?

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

(И это шаблон disruptor все еще намного быстрее, чем другие блокированные многопроцессорные многопользовательские очереди (например, от boost), когда несколько продюсеров (т.е. Операции CAS)?


Мое положение подробно:

Обработка записи может привести к появлению нескольких новых записей, которые также должны быть обработаны. Производительность имеет наивысший приоритет, записи, обрабатываемые в порядке FIFO, имеют второй приоритет.

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

Использование шаблона разрушителя будет гарантировать порядок FIFO. Но не будет ли распространять записи на потоки, вызывая гораздо более высокий конфликт (например, CAS на курсоре чтения), чем для локальных FIFO с кражей работы (каждая пропускная способность потока примерно одинакова)?


Ссылки, найденные мной

Тесты производительности в стандартном техническом документе о разрушителе (глава 5 + 6) не охватывают непересекающееся распределение работы.

https://groups.google.com/forum/?fromgroups=#!topic/lmax-disruptor/tt3wQthBYd0 - это единственная ссылка, которую я нашел на краже или краже работы. В нем указано, что очередь на поток значительно медленнее, если есть какое-либо общее состояние, но не входит в детали или объясняет почему. Я сомневаюсь, что это предложение относится к моей ситуации:

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

Ответ 1

Обновление - нижняя строка впереди для максимальной производительности: вам нужно написать как в идиоматическом синтаксисе для разрыватора, так и во время кражи работы, а затем провести тест.

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

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

  • Используйте disruptor, когда ваша реализация ориентирована на . Каждый поток может работать на определенной стадии обработки. Альтернативный пример: для фокуса задачи обработка будет разделена на этапы, поэтому у вас будет поток, который выполняет протоколирование, поток для элементов управления безопасностью, поток для поиска в vhost и т.д.; каждый поток фокусируется на своей задаче и передает запрос на следующий поток в конвейере. Этапы могут быть параллельными, но общая структура представляет собой поток, ориентированный на конкретную задачу, и передает сообщение между потоками.

Конечно, вы можете изменить свою реализацию в соответствии с каждым подходом лучше.

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

Еще несколько подробностей:

  • Disruptor - очень полезно, когда требуется строгий порядок этапов, дополнительные преимущества, когда все задачи имеют согласованную длину, например: отсутствие блокировки внешней системы и очень похожий объем обработки на одну задачу. В этом случае вы можете предположить, что все потоки будут работать равномерно через систему и, следовательно, организовать N потоков для обработки каждого N сообщений. Мне нравится думать о Disruptor как об эффективном способе реализации SEDA-подобных систем, где потоки обрабатывают этапы. Разумеется, вы можете иметь приложение с одной ступенькой и несколькими параллельными блоками, выполняющими одну и ту же работу на каждом этапе, но на самом деле это не так. Это полностью исключало бы стоимость совместного состояния.
  • Кража работы - используйте это, когда задачи имеют разную продолжительность, а порядок обработки сообщений не важен, поскольку это позволяет потокам быть свободными и уже потребляет свои сообщения для продолжения прогресса из другой очереди задач. Таким образом, если, например, у вас есть 10 потоков и 1 заблокирован на IO, остаток все равно завершит их обработку.