LINUX.ORG.RU

Как в очередях регулируют нагрузку процессора?

 


0

3

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

Самое простое, это сделать воркеры однотредовыми и выгребать за раз по 1 задаче. Но даже если задача «тяжелая», у нее могут быть операции I/O, где процессор простаивает. Первое что приходит в голову - сделать воркеров в пару раз больше чем ядер, это вроде решит проблему с размазыванием нагрузки на проц.

А как быть если задача «долгая», но не сильно грузит CPU? Например, сканирование URL. Там время уходит на скачивание файла, а проц стоит. И что не очень приятно, если прилетит пачка таких задач (больше чем воркеров), они могут например тормознуть отправку писем (более приоритетные задачи).

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

UPD. Воркер - процесс node.js, то есть кооперативность на уровне IO там есть.

★★★★★

Но даже если задача «тяжелая», у нее могут быть операции I/O, где процессор простаивает.

Ну он не простаивает. Он ждет прерывания на чтение и потом отпускает syscall и твой процесс продолжает работать. В это время шедулер ОС сам за тебя переключит задачу.

А как быть если задача «долгая», но не сильно грузит CPU?

Она все равно будет блокироваться на вызове write/read(send/recv) и шедулер с большой вероятностью посчитает что пора переключится. Тем более у шедулера есть метрики для определения был ли выработан выделенный квант времени. CFS работает как раз на https://en.wikipedia.org/wiki/Weighted_fair_queueing. Ты, конечно, может прочесть тонны литературы и написать свой шедулер, но кажется это не совсем то, что тебе нужно.

они могут например тормознуть отправку писем (более приоритетные задачи).

Например, можно повысить приоритет с помощью setpriority/pthread_setschedparam. Зависит от того, что ты хочешь получить.

xpahos ★★★★★ ()

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

Не решит. Возможно сделает еще хуже.

Насколько тебе доступны внутренности твоих воркеров? Возможно удастся сделать кооператвную многозадачость: M юзерленд тредов выполняющихся на N нативных тредах, когда треду нужно сделать ИО он запускает операцию (неблокирующую на самом деле) и делает yeld(). Планировщик таки придется написать.

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

anonymous ()
Ответ на: комментарий от xpahos

Ты наверное не до конца понял вопрос. Считаем что есть одна нода, которая занимается исключительно очередью. То есть:

1. можем выполнять тяжелые вычисления
2. можем фик знает сколько ждать ответа удаленного сервера (например скачиваем картинку, а удаленный сервер раздупляется только через 5 секунд)
3. можем внутри задачи читать или писать по сети в базу (отдельный простой небольшой, но в сумме может набежать)
4. можем ничего не делать при отсутствии задач

В идеале - хочется чтобы все ядра были нагружены на 100% и чтобы подвисающие задачи не тормозили более приоритетные.

На практике, я могу нафоркать по 2 воркера на ядро, сказать чтобы воркер вытягивал не более 1 задачи любого типа за раз (сначала из списка самых приоритетных, потом из менее приоритетных и т.п.). И самостоятельно позаботиться о том, чтобы длинных провисаний было не много.

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

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

Vit ★★★★★ ()

Принцип «разделяй и влавствуй». Разбей задачу на группы и каждую группу обрабатывай отдельно, т.е. отдельным пулом потоков.

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

Задачи с интенсивным IO можно выполнять на большем пуле, потому что будут простои на sleep и блокировках. С интенсивными вычислениями - на меньшем пуле, потому что они жрут процессор.

Общего рецепта нет. Может быть, то, как ты разобьешь задачи, и есть архитектура приложения.

Существуют целые весьма нехилые фреймворки, такие как akka, которые посвящены этой теме.

dave ★★★★★ ()
Последнее исправление: dave (всего исправлений: 1)
Ответ на: комментарий от anonymous

Насколько тебе доступны внутренности твоих воркеров? Возможно удастся сделать кооператвную многозадачость: M юзерленд тредов выполняющихся на N нативных тредах, когда треду нужно сделать ИО он запускает операцию (неблокирующую на самом деле) и делает yeld(). Планировщик таки придется написать.

Там жабаскрипт, то есть считай что внутри есть кооперативная многозадачность на уровне вызовов I/O, а для нативных тредов просто форкается нужное количество процессов node.js.

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

Vit ★★★★★ ()
Ответ на: комментарий от dave

Надо уточнить терминологию, потому что везде она разная. Я задачами называю минимальную «не делимую» логически осмысленную вещь. Например:

- перестроить 100 постов (разбивка 1М на блоки по 100 делается отдельно)
- отправить 1 письмо (обычно из возникает по 100 штук)
- узнать размеры картинок в посте (1-30 URL при создании поста)

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

Vit ★★★★★ ()

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

iliyap ★★★ ()

А в чём проблема сделать долгие операции асинхронными с коллбэками по окончанию долгих операций? Пока ждёт I/O - выполняется логика основного потока. Или её почти нету?

На высоком уровне всё упирается в разделение задач c I/O и задач с CPU - они должны работаться параллельно с передачей данных друг другу.

Соответственно, количество CPU воркеров - количество ядер, количество IO воркеров - в зависимости от твоей инфораструктуры.

Shtsh ★★★★ ()
Ответ на: комментарий от Shtsh

С такой логикой надо запустить сразу все задачи одновременно :)

Мы живем не в идеальном мире, и нет задач с чистым IO и с чистым CPU. Максимум что реально прописать ручками - что отправка почты более приоритетна чем ребилд постов.

Vit ★★★★★ ()
Ответ на: комментарий от Vit

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

dave ★★★★★ ()
Последнее исправление: dave (всего исправлений: 1)

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

А с твоими запросами именно это и получится. Кривое и полурабочее, как и все попытки сделать ОС в юзерспейсе.

tailgunner ★★★★★ ()

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

Тут конечно не освещена сторона персистентности, но сделаем предположение что это БД

Здесь тогда всё просто:

БД <-> Координатор ака <пул воркеров> ->>> воркеры

Опять таки, вопрос транзакций здесь тоже остается открытым.

Таким образом, если главный тезис это:

Но может можно сделать как-то красивее? Без превращения кода в ад.

Лучше оставить как есть, ИМХО:

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

Просто, очевидно, и должно работать с приемлимой производительностью. Не трейдинговую систему ж пишешь

Ай, да это же НОДА, воркеры то однопоточные. Вот тут и корень всех бед.

Тогда очередь с приоритетами да и всё.

Пусть воркер выгребает сначала задачи более приоритетного типа, если их нет - то менее, и так до задач которые раскрашивают лог файлы в зависимости от настроение луны

anonymous ()
Ответ на: комментарий от Vit

Да, теперь понятнее, но все равно приблизиться к 100% не получится. У тебя получится очень сложный планировщик, которому нужно будет учитывать среднее время выполнения таска по куче метрик и количество блокировок при переходе в kernel space. Например, скачивание картинки с удаленного сервера. Нужно будет понимать какой канал до сервера, сколько он может отдать тебе данных итд. Возможно скачивание картинки с Акамаи будет быстрее, чем одуплится твой почтовый сервер.

xpahos ★★★★★ ()
Ответ на: комментарий от dave

Вполне можно. Не задумывался. А по какому принципу группировать?

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

Если по приоритетам (high/normal/low), то это в принципе облегчит жизнь на уровне «чтобы отправка писем не тормозила», но не решит в общем случае. Хотя не знаю, может в общем случае и не надо.

С очередью 2 проблемы:

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

Насчет второго пункта идеи есть? Самое простое что я придумал - сделать воркеров в пару раз больше чем ядер, чтобы дырки «перекрылись». Ну а то что в пике загрузка будет запрашиваться в 2 раза больше чем позволяет железка - разрулится системным шедюлером.

Vit ★★★★★ ()
Ответ на: комментарий от tailgunner

Запросы у меня гибкие, в меру понимания очередей, которыми особо никогда не пользовался :)

Другие же очереди работают как-то. Лучше б по делу чего предложил.

Vit ★★★★★ ()
Ответ на: комментарий от Vit

Ты сформулировал задачу в таком общем виде, что предложить тебе можно только «распределяй на узлы желаемое тобой количество работы». А если в твоем случае количество и характер работы непредсказуемы, остается только полагаться на механизмы ОС - они сделаны для работы как раз в такой ситуации.

tailgunner ★★★★★ ()
Ответ на: комментарий от xpahos

Там 2 разные проблемы:

1. Тяжелая задача, 1-5 сек 100% нагрузки но с небольшими дырками (парсим/генерим блоки из 100-10000 постов с запросами к базе в промежутках) - не донагрузит ядро проца.

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

Сложного планировщика не хочу. Плохо это. Разумным выглядит сделать избыточное количество воркеров (скинув остальные сложности на системный шедюлер). Крайний случай - по ХХ воркеров (количество ядер*2) на каждый тип задачи, но это слишком избыточно.

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

Vit ★★★★★ ()
Ответ на: комментарий от tailgunner

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

Про то что надо полагаться на механизмы ОС я и так в курсе. Вопрос в том, как правильно разделить логику - что оставить в юзерспейсе (процессе воркера), а что скинуть на OC (путем создания копий воркеров).

Vit ★★★★★ ()
Ответ на: комментарий от Vit

Если у тебя 100500 воркеров, то ты только сделашь хуже. Они будут переключаться между собой, а context switch это всегда плохо. И про загрузку процессора несколькими задачами на 100% можно забыть, если у тебя не тру RISC процессор. У Intel очень много костылей и там внутри есть штука, которая сначала кучкует код в один поток, а потом параллелит внтури сам. Я не помню как это называется. В общем это нужно чтобы если у тебя возникнет деление на ноль, например, то процессор имел бы корректное состояние, а не хаотичные значения регистров и прочего.

xpahos ★★★★★ ()
Ответ на: комментарий от xpahos

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

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

Пока склоняюсь к тому, что надо сгруппировать задачи и выделить разным группам разные воркеры:

1. Гарантированно тяжелые задачи (ребилды постов) гоним в heavy воркеры. Воркеров 2*ядро. Запускаем строго по 1 задаче на воркер.

2. Остальные задачи гоним в generic воркеры. Воркеров от 1 до количества ядер. Запускаем параллельно по 1 задаче каждого типа.

Vit ★★★★★ ()
Ответ на: комментарий от Vit

Поправочка - для легких задач параллельно можно пускать ХХ каждого типа. Конкретное число разработчик может указать при регистрации типа задачи. Но это уже мелкий и не очень принципиальный нюанс.

Vit ★★★★★ ()
Ответ на: комментарий от Vit

Имхо, тогда лучше n-1 воркеров для тяжелых задач и 1 на легкие. Переключений будет меньше. Вообще погоняй с разными значениями и посмотри на load average. Если он будет большой, то что-то ты делаешь не так.

xpahos ★★★★★ ()
Ответ на: комментарий от xpahos

Ну LA показывает количество ожидающих процессов, так что будет в среднем = количество занятых тяжелых воркеров плюс-минус лапоть. Я с этим довольно много развлекался, и могу сказать что если количество процессов в системе фиксированное, то почти без разницы будет ли LA 1, 5 или 20. Просадки начинаются обычно на диске с WA > 10%, когда в базу много пишут. В этом случае растут лаги на запросах к базе и рабочие процессы не могут полностью нагрузить ядра.

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

Vit ★★★★★ ()
Ответ на: комментарий от Vit

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

Как-то решал задачку и мы решили посоревноваться у кого она будет быстрее. Я посидел с Intel vtune amplifier и смог немного ее заоптимизировать. Это не самая умная мысль профилировать приложение с помощью vtune, но на 100% покажет что не так. Вообще я про него узнал из Intel лекции, где чувак рассказывал как они упарываются по оптимизации. После лекции понял что не знаю ничего про процессоры и решил таки разобраться хотя бы с MIPS и свой написать :)

xpahos ★★★★★ ()

Возьми модуль cluster
В ноде неблокирующий IO, если кто-то будет ждать чего-то, то выделенные на него ресурсы сами уменьшаться
Если лезть в дебри в регулировкой, то получишь тормоза
Просто cluster-ом форкаешься на число ядер и все

mystery ★★ ()
Ответ на: комментарий от xpahos

Так и запишем... ответил уклончиво :)

Послушай, в мире есть много интересных инструментов, но нельзя просто так тратить время на новые технологии. Должны быть хоть какие-то грубые оценки. Например, «на 20 процессах затраты на переключение контекста обычно не превышают 1%».

Vit ★★★★★ ()
Ответ на: комментарий от Vit

Мне очень лениво гуглить. Если память не изменяет, то один cs получается меньше 2000ns. Кэшмис первого уровня около 100 ns, второго уровня 150ns. Так, а дальше у нас CFS, у него нижняя планка около 1 ms(по-моему меньше) и верняя плавающая больше 5 ms. Т.е. это гарантирует что процесс переключится не более чем через эти 5 ms, если нет более приоритетных задач. Там у шедулера есть еще FIFO задачи и RoundRobin, а user space по-моему OTHER называются. Хотя может быть уже все не так, я ковырял 2.6 -> 3.x еще по старым книжкам.

xpahos ★★★★★ ()
Ответ на: комментарий от xpahos

Можешь перевести на человеческий? Например, после скольки процессов (тредов?) на ядро надо беспокоиться о CS. Снизойди уже от удивительных энциклопедических фактов до простых прикладных задач :)

Vit ★★★★★ ()
Ответ на: комментарий от Vit

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

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

Число воркеров делается равным числу ядер - 1 только в одном случае, когда задачи вычислительные, но это явно не ваш случай.

dave ★★★★★ ()
Ответ на: комментарий от Vit

Конечно, если разбивать на группы воркеров, то уже нет смысла слишком раздувать количество воркеров в группе. Гадая пальцем в небо, скажем, если 10 групп воркеров, то в каждой группе - по 5-10 воркеров. Это очень грубая прикидка.

Просто слишком много потоков - тоже плохо, потому что имеем частое переключение контекста, сброс кешей и прочие радости жизни. Но у вас в ноде потоки какие, зеленые или нативные?

dave ★★★★★ ()

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

ya-betmen ★★★★★ ()
Ответ на: комментарий от dave

Просто слишком много потоков - тоже плохо, потому что имеем частое переключение контекста, сброс кешей и прочие радости жизни.

А «много» это сколько? Какого порядка цифры? У меня количество потоков в том же порядке что количество ядер. Ну то есть абсолютно точно не в 10 раз больше.

Например прямо сейчас при 4 ядрах висит 8 процессов на вебсервер и 8 на очередь. Времени пока особо не было тюнить, слепили просто на глаз левой ногой.

Но у вас в ноде потоки какие, зеленые или нативные?

Там даже не потоки, а просто асинхронный код. Ближайший аналог наверное green threads или кооперативная многозадачность, если я не путаю термины.

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

Vit ★★★★★ ()
Ответ на: комментарий от dave

Ну пока советы были хорошие, за что большое спасибо.

Проблема примерно следующая. Есть много «небольших» проектов, где очень избыточно подходить по ынтырпрайзному, разворачивая полноценные очереди типа celery + rabbitmq и прочую хренотень.
В этой нише удобно иметь встраиваемое решение попроще, например на редисе и наличие точки отказа не фатально. Достаточно если будет eventual consistency данных.

Соответственно, я конкретно под ноду иногда в прорядке развлечения проектирую качественные лисапеды, сорцы можно наблюдать по ссылкам в профиле. Для внутреннего применения уже слепили очередь https://github.com/nodeca/nodeca.core/tree/master/lib/queue, но по результатам использования и перед выкладыванием для всех, захотелось ее улучшить. Основная причина - обеспечить равномерную плотность чанков на больших задачах, тема тут www.linux.org.ru/forum/development/12838204. Ну и раз уж клепать навороты, захотелось всякие популярные фишки вроде group/chain добить, и разобраться как нагрузка распределяется.

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

Vit ★★★★★ ()
Ответ на: комментарий от Vit

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

ya-betmen ★★★★★ ()
Ответ на: комментарий от Vit

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

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

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

Хотя у нас аналогичная система вполне тянет 1000 потоков с хорошим таким IO, но там архитектура решения другая, не через пул, а напрямую на потоках. И большую часть времени потоки висят или на sleep, или на select, или на блокировках. Там линукс вполне справляется из-за того, что нет частого переключения контекста.

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

С зелеными тредами ситуация другая, но я с ними особо не работал на таком уровне, как с системными, хотя в моем любимом хаскеле основными являются как раз зеленые потоки, но привязанные к системным нативным потоки там тоже есть.

dave ★★★★★ ()
Ответ на: комментарий от dave

Спасибо. А больше 2 пулов на практике часто приходилось делать? У меня пока получается так:

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

Это конечно очень схематично, просто хочу понять какие конфигурации в первую очередь проверять.

Vit ★★★★★ ()
Ответ на: комментарий от Vit

Системы с количеством пулов (>> 1) существуют. Примеры можно увидеть в Scala Akka.

Можно разбить на типы задач. И каждый тип обрабатывать своим пулом. Что-то можно объединить.

dave ★★★★★ ()
Ответ на: комментарий от ya-betmen

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

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

Vit ★★★★★ ()
Ответ на: комментарий от dave

Правильно ли я понимаю, что при наличии пулов понятие «приоритет задачи» становится ненужным? При условии что у пула есть опция всасывать задачи параллельно.

https://github.com/Automattic/kue это самая популярная очередь под ноду (исторически сложилось), но там пулов нет и мнится мне, спроектировано это было не подумавши.

Vit ★★★★★ ()
Ответ на: комментарий от Vit

Правильно ли я понимаю, что при наличии пулов понятие «приоритет задачи» становится ненужным?

Меня тоже этот вопрос интересует)

В boost asio полноценного ответа для себя не нашел, кроме крохотного примера из документации. В scala akka тоже не вижу, хотя, быть может, мало смотрел документацию. Как в .NET в стандартном пуле потоков уже не помню, но, допускаю, что приоритетов прямых там нет.

dave ★★★★★ ()
Ответ на: комментарий от Vit

Не нужно ничего начинать сначала, то что тебе что-то не нравится в этом решении не значит что само решение плохое. Ты просто определись для начала что тебе нужно: на 100% загруженный проц или наиболее эффективная его загрузка? Можешь ли ты заранее «угадать» профиль нагрузки того или иного таска? Если можешь значит можно крутить алгоритм выбора следующей задачи если нет то ничего лучше чем системный шедулер и эмпирический подбор максимального и минимального числа параллельных таксов и скользящего среднего для расчета текущей нагрузки не найдешь.

ya-betmen ★★★★★ ()
Ответ на: комментарий от dave

Меня тоже этот вопрос интересует)

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

Если же приоритетам соответствуют квоты (скажем, приоритету p0, самому низкому выделена квота 10, приоритету p1 — квота 15, приоритету p2 — квота 20 и т.д.), то какая штука на пул потоков вполне себе ложится.

Например, есть 150 задач с приоритетом p0, 20 задач с приоритетом p1 и 5 задач с приоритетом p2. Сначала берется 5 задач p2. Квота полностью не выбрана, но и задач p2 не осталось. Поэтому следом берется 15 задач p1. Квота выбрана полностью, поэтому выполняется переход к p0 и обрабатывается 10 задач p0. Квота выбирается и выполняется переход вновь к p1, т.к. там осталось еще 5 задач. Потом опять к p0. И обработка p0 продолжается до тех пор, пока не появятся задачи с более высоким приоритетом.

eao197 ★★★★ ()
Ответ на: комментарий от eao197

Зависит от того, как воспринимать приоритет.

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

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

И вот есть подозрение, что если можно создавать произвольное количество пулов нужного размера и конфигурить роутинг задач, то приоритет там не нужен от слова «совсем».

Vit ★★★★★ ()