Какую выгоду получает Акка от ForkJoinPool? - PullRequest
0 голосов
/ 05 октября 2018

Akka docs утверждает, что диспетчером по умолчанию является fork-join-executor, потому что он "дает отличную производительность в большинстве случаев".
Мне интересно, почему это так?

С ForkJoinPool

ForkJoinPool отличается от других видов ExecutorService в основном за счет использования кражи работы: все потоки в пуле пытаются найти и выполнитьзадачи, переданные в пул и / или созданные другими активными задачами (в конечном итоге блокирование ожидания работы, если таковой не существует)Это обеспечивает (1) эффективную обработку, когда большинство задач порождают другие подзадачи (как и большинство ForkJoinTasks) , а также (2), когда множество небольших задач передается в пул от внешних клиентов ,Особенно при установке asyncMode в true в конструкторах, ForkJoinPools может также (3) подходить для использования с задачами в стиле событий, которые никогда не объединяются.

Сначала я предполагаю, чтоAkka не является примером case (1), потому что я не могу понять, как Akka может выполнять задачи, я имею в виду, что будет задачей, которую можно выполнить во многих задачах?
Я вижу каждое сообщение какнезависимая задача, поэтому я думаю, что Akka похож на случай (2), где сообщения представляют собой множество небольших задач, отправляемых (через! и?) в ForkJoinPool.

Следующим вопросом, хотя и не связанным строго с akka, будет , почему случай использования, в котором не используются fork и join (основные возможности ForkJoinPool, позволяющие выполнять кражу рабочих данных), все еще можетбыть полезным для ForkJoinPool?
с Масштабируемость пула соединений Fork

Мы заметили, что число переключений контекста было ненормальным, выше 70000 в секунду.
Это должно быть проблемой, но чем это вызвано?Виктор выдвинул квалифицированное предположение, что это должна быть очередь задач исполнителя пула потоков, поскольку она является общей, и блокировки в LinkedBlockingQueue могут потенциально генерировать переключение контекста при возникновении конфликта .

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

Итак, мои вопросы:

  1. Akka использует ForkJoinTasks (case (1)) или относится к case (2)?
  2. Почему ForkJoinPoolвыгодно в случае (2), если все эти задачи, отправленные внешними клиентами, будут помещены в общую очередь и не будет происходить кража работы?
  3. Что может быть примером "с задачами в стиле событий, которыеникогда не присоединялся "(случай 3)?

Обновление

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

  • Akka не использует fork и joinвозможности, начиная с AFAIK с моделью Actor, или, по крайней мере, как мы ее реализуем, для этого (из комментария Йоханандрена) на самом деле нет прецедента.
    Так что я понимаю, что Akka не является примером case (1) было правильно.
  • В своем первоначальном ответе я сказал, что все задачи, отправленные внешними клиентами, будут поставлены в очередь в общей очереди .
    Это было правильно, но только для предыдущей версии (JDK7) из FJP.В jdk8 единичная очередь выдачи была заменена множеством "очередей отправки". Этот ответ объясняет это хорошо:

    Теперь, до (IIRC) JDK 7u12, ForkJoinPool имел единую глобальную очередь отправки.Когда у рабочих потоков закончились локальные задачи, а также задачи для кражи, они попали туда и попытались проверить, доступна ли внешняя работа.В этом проекте нет никаких преимуществ перед обычным, скажем, ThreadPoolExecutor, поддерживаемым ArrayBlockingQueue.[...]
    Теперь внешняя отправка попадает в одну из очередей отправки.Затем работники, которым нечем заняться, могут сначала заглянуть в очередь отправки, связанную с конкретным работником, а затем побродить, просматривая очереди отправки других.Можно также назвать это «кражей работы».

Таким образом, это включало кражу работы в сценариях, где не использовалось форк-соединение.Как говорит Даг Ли,

Значительно лучшая пропускная способность, когда множество клиентов выполняет много задач.(Я измерял до 60-кратного микробенчмарка Speedupson).Идея состоит в том, чтобы обращаться с внешними отправителями так же, как с работниками, используя рандомизированные очереди и кражи.(Это потребовало большого внутреннего рефакторинга, чтобы разъединить рабочие очереди и рабочих.) Это также значительно улучшает пропускную способность, когда все задачи асинхронны и передаются в пул, а не разветвляются, что становится разумным способом структурировать структуры акторов, а также многие обычные сервисы, которые вы могли бы использовать в противном случае.ThreadPoolExecutor для.

  • Есть еще одна особенность, о которой стоит упомянуть, о FJP, взятом из этого комментария

    4% действительно не так много для FJP,С FJP вы по-прежнему должны идти на компромисс, о котором вам необходимо знать: FJP некоторое время продолжает вращать потоки, чтобы иметь возможность быстрее обрабатывать прибывающую работу.Это обеспечивает хорошую задержку во многих случаях.Тем не менее, особенно если ваш пул сверхобеспечен, компромисс - это небольшая задержка с увеличением энергопотребления в почти бездействующих ситуациях.

Ответы [ 2 ]

0 голосов
/ 11 октября 2018

http://letitcrash.com/post/17607272336/scalability-of-fork-join-pool

Масштабируемость пула соединений Fork

Пропускная способность передачи сообщений Akka 2.0 на многоядерном оборудовании значительно лучше, чем в предыдущих версиях, благодаря новому исполнителю fork join, разработанномуДаг Ли.Один микро-тест показывает увеличение пропускной способности на 1100%!

...

http://cs.oswego.edu/pipermail/concurrency-interest/2012-January/008987.html

...

Основные характеристики:

  1. Значительно лучшая пропускная способность, когда множество клиентов отправляют множество задач.(Я измерял до 60-кратного ускорения на микробенчмарках).Идея состоит в том, чтобы обращаться с внешними отправителями так же, как с работниками, используя рандомизированные очереди и кражи.(Это потребовало большого внутреннего рефакторинга для разъединения рабочих очередей и рабочих.) Это также значительно повышает пропускную способность, когда все задачи асинхронные и отправляются в пул, а не разветвляются, что становится разумным способом структурирования структур акторов, а также многих простых служб.что вы могли бы иначе использовать ThreadPoolExecutor для.

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

...

0 голосов
/ 10 октября 2018

FJP в Akka запускается с asyncMode = true, поэтому для первого вопроса: внешние клиенты отправляют короткие / небольшие асинхронные рабочие нагрузки.Каждая отправленная рабочая нагрузка либо отправляет актера для обработки одного или нескольких сообщений из своего почтового ящика, но также используется для выполнения операций Scala Future.

Когда запланировано выполнение не-ForkJoinTask наFJP, он адаптирован к FJP и ставится в очередь так же, как ForkJoinTask s.Не существует ни одной отправки, где задачи ставятся в очередь (в ранней версии, возможно, JDK7), существует множество, чтобы избежать конфликтов, и свободный поток может выбирать (красть) задачи из других очередей, чем его собственная, если это так.empty.

Обратите внимание, что по умолчанию мы в настоящее время работаем на разветвленной версии Java 8 FJP, так как мы увидели значительное снижение пропускной способности с Java 9 FJP, когда он появился (он содержит довольно мало изменений),Вот вопрос № 21910, в котором обсуждается , если вы заинтересованы.Кроме того, если вы хотите поиграть с тестами различных пулов, вы можете найти несколько *Pool тестов здесь: https://github.com/akka/akka/tree/master/akka-bench-jmh/src/main/scala/akka/actor

...