N>Они точно меряют оверхед шедулера, а не, например, динамической типизации?
Не знаю, не смотрел еще. Как не успел посмотреть и distributed actors из Swift, которые, по уверениям автором, inspired by Erlang. Некогда было, и так дел невпроворот. Все никак не доделаю heap profiling в этом самом BEAM...
N>А они тут неотделимы. Я про всё тот же single input mailbox, на все жалобы на который от вас кроме как "это у вас руки кривые" ответов нет.
Прям детская травма какая-то. Да есть в BEAM реализация priority send, сделана на базе signals (относительно новая концепция, 4 года все как). Просто конкретика применения может быть очень и очень сомнительна, ибо позволяет очень уверенно выстрелить себе в ногу. Тот самый компромисс (который и в ETS есть, благодаря чему так часто и стреляют то в ногу, то в руку, создавая contention).
И как же в Go это решили? Ничтоже сумняшеся сразу имели priority queue (или priority send)?
Здравствуйте, SkyDance, Вы писали:
N>>А они тут неотделимы. Я про всё тот же single input mailbox, на все жалобы на который от вас кроме как "это у вас руки кривые" ответов нет.
SD>Прям детская травма какая-то.
Полностью взрослая с соответствующей обоснованной реакцией.
Детское поведение — это у Erlang/OTP core team (да, я помню, что она как-то иначе зовётся), которые игнорируют все разумные доводы, несмотря на то, что большинство уже внуками обзавелось.
SD> Да есть в BEAM реализация priority send, сделана на базе signals (относительно новая концепция, 4 года все как).
Прошу точные ссылки, ибо не гуглится.
SD> Просто конкретика применения может быть очень и очень сомнительна, ибо позволяет очень уверенно выстрелить себе в ногу.
Примеры "выстреливания в ногу" в студию.
SD>И как же в Go это решили? Ничтоже сумняшеся сразу имели priority queue (или priority send)?
Решено комплексно:
1. Возможность читать из любого канала, а не из одного фиксированного на горутину (аналог процесса Erlang). Зная, кому послал сообщение в синхронном варианте — ждать ответа из канала, про который договорились, что придёт ответ в него.
2. `select` на несколько каналов ввода выбирает из так, что за один круг прохождения select (столько раз, сколько каналов в нём описано) каждый канал оказывается проверен по разу.
Этого достаточно для того, чтобы не было непредсказуемо долгого ожидания важного сообщения в хвосте очереди из неважных.
А если просто цепочка selectʼов с default — то получается и явная приоритизация. Более громоздко, но действенно.
Поскипал много букв.
Просто один вопрос от капитана очевидность- об очереди с приоритетом плюсники не слыхали?
Купите им кто-нибудь книжку по алгоритмам и структурам данных.
Зарыто где-то в pull requests, вкратце — вот реализация. Начиная где-то с OTP21 очередь сообщений процесса уже не одна, а две — с priority сигналами и с обычными messages. Но сами сигналы пока открыты только для использования системными функциями. Пример: process_info, который имеет приоритет перед обычными сообщениями. Патч по ссылке сверху добавляет приоритетный сигнал "вставь сообщение в голову внутренней очереди".
Реализация-то несложная, но последствия существования подобных API ведут к нетривиальным эффектам. Не хочется, чтоб Эрланг превращался в С++, вся его суть — чтоб было проще reason about.
N>Примеры "выстреливания в ногу" в студию.
Нарушение порядка сообщений между двумя процессами. Это базовая гарантия Эрланга, на ней построено много чего.
N>1. Возможность читать из любого канала, а не из одного фиксированного на горутину
То есть вместо message queue имеем просто socket'ы. Прелестно. Надо ли говорить, насколько сложнее тестировать подобное поведение? Машина состояний намного более сложная. А сложность есть главный враг инженера.
N> Зная, кому послал сообщение в синхронном варианте — ждать ответа из канала, про который договорились, что придёт ответ в него.
Это решается с помощью selective receive, который в свежих версиях уже умеет multiple receive markers (устраняя необходимость в линейном сканировании всех сообщений в очереди). Реализация, однако, там довольно hacky, и для работы требует чтобы сообщение было tuple, где первым элементом идет ref (сделаный либо make_ref, либо erlang:monitor, либо чем-то еще аналогичным, типа timer).
Единственный marker был там очень давно (точно был в OTP 16), так что одиночный синхронный вызов и раньше работал без сканирования очереди. Но multicall — свежачок-с, буквально в этом году заработал. Плюс куча других удобств типа process aliases, защищающих от отправки late replies (когда процесс уже и не ждет результатов синхронного вызова).
Я каждый раз вижу, как все это пере-изобретается в других рантайманх, и думаю, когда же они наконец догонят. Это, как мне кажется, неизбежно. Но будет ли синтаксис столь удобный, и рантайм достаточно эффективный — вопрос.
Здравствуйте, SkyDance, Вы писали:
SD>Зарыто где-то в pull requests, вкратце — вот реализация. Начиная где-то с OTP21 очередь сообщений процесса уже не одна, а две — с priority сигналами и с обычными messages. Но сами сигналы пока открыты только для использования системными функциями. Пример: process_info, который имеет приоритет перед обычными сообщениями. Патч по ссылке сверху добавляет приоритетный сигнал "вставь сообщение в голову внутренней очереди".
"Патч по ссылке сверху" уже полтора года стоит в ожидании у моря погоды. Никакого "начиная где-то с OTP21" нет, патч уже даже не мержится. Я, конечно, рад, что хоть кто-то начал такое предлагать и его не зарежектили мгновенно — это даёт надежду, что не прошло и 40 лет, как разум начал появляться в головах разработчиков. Но всё это начинает напоминать, как Торвальдс орал матом на весь интернет про "silly triplet" в kqueue, а затем принял то же самое 1:1 в epoll, потому что его сделали не чужие люди, а собственный подхалим.
SD>Реализация-то несложная, но последствия существования подобных API ведут к нетривиальным эффектам. Не хочется, чтоб Эрланг превращался в С++, вся его суть — чтоб было проще reason about.
"Нетривиальный эффект" нормального QoS это не что-то особенное, это банальная база, без которой в таких задачах вообще никуда.
И это я не вспоминаю, что selective receive уже даёт то же самое, но дороже.
N>>Примеры "выстреливания в ногу" в студию. SD>Нарушение порядка сообщений между двумя процессами. Это базовая гарантия Эрланга, на ней построено много чего.
А достаточно всего лишь в формулировку гарантии добавить "в пределах одной очереди", потому что посылки в разные очереди всё равно делаются явно.
N>>1. Возможность читать из любого канала, а не из одного фиксированного на горутину SD>То есть вместо message queue имеем просто socket'ы. Прелестно.
Нет, не сокеты. Сходи к документации. Это именно что каналы взаимодействия между горутинами, внутреннее API, только иначе сгруппированное. Там нельзя послать произвольное сообщение произвольной горутине, только зная её идентификатор — это, возможно, недостаток. Но возможность приоритетного чтения пересиливает его для типовых задач.
SD> Надо ли говорить, насколько сложнее тестировать подобное поведение? Машина состояний намного более сложная. А сложность есть главный враг инженера.
И это говорит сторонник одного входного канала на процесс? Вот где действительно сложность в управлении потоками на этом всём.
Я не скажу, что подход Go, особенно с рандомностью порядка чтения, это лучший вариант. Но именно от заторов он избавляет просто и эффективно.
И надо учесть, что Go заточен под работу инженера типа Индус Обобщённый Фольклорный Типовой (ИОФТ), который раздумья над качеством деталей реализации заменяет 20 запусками ручного теста, поэтому в таком контексте, возможно, это идеальное решение.
N>> Зная, кому послал сообщение в синхронном варианте — ждать ответа из канала, про который договорились, что придёт ответ в него.
SD>Это решается с помощью selective receive, который в свежих версиях уже умеет multiple receive markers (устраняя необходимость в линейном сканировании всех сообщений в очереди). Реализация, однако, там довольно hacky, и для работы требует чтобы сообщение было tuple, где первым элементом идет ref (сделаный либо make_ref, либо erlang:monitor, либо чем-то еще аналогичным, типа timer).
Ну вот пока эти люди будут вместо простого, эффективного, надёжного, легко управляемого и понятного использовать подобные хаки — нормальной работы не будет.
SD>Единственный marker был там очень давно (точно был в OTP 16), так что одиночный синхронный вызов и раньше работал без сканирования очереди. Но multicall — свежачок-с, буквально в этом году заработал. Плюс куча других удобств типа process aliases, защищающих от отправки late replies (когда процесс уже и не ждет результатов синхронного вызова).
Late reply это минимальная проблема, и выгибаться для неё как-то не стоило. Более того, иногда он крайне полезен логанием хотя бы темпа таких опозданий.
Такое впечатление, что упор идёт на минимизацию межнодового обмена. Может, это и ценное направление для некоторых применений, но не абсолютное.
По-нормальному multicall типа "один ответил, остальных сразу игнорим" должен рассматриваться особо.
SD>Я каждый раз вижу, как все это пере-изобретается в других рантайманх, и думаю, когда же они наконец догонят. Это, как мне кажется, неизбежно. Но будет ли синтаксис столь удобный, и рантайм достаточно эффективный — вопрос.
Видимо, у них задачи другие. По сравнению с вопросом, когда же Erlang догонит конкурентов в части приоритизации, это выглядит просто мелко.
N>"Патч по ссылке сверху" уже полтора года стоит в ожидании у моря погоды.
Я же объяснил, почему. Несмотря на простоту реализации, этот подход вносит неопределенность в существующую модель, ломая базовую гарантию доставки сообщений между двумя процессами. Сделать-то легко, но расхлебывать потом... за что я и люблю Erlang, 30 лет на сцене, но все еще очень конкретный и понятный.
N> Никакого "начиная где-то с OTP21" нет, патч уже даже не мержится.
Начиная с OTP21 там есть очередь сигналов. До 21 не было, сигналы вообще не были асинхронными, что порой мешало realtime'у. Я именно про это писал, а не про патч (который, в разных формах, еще Rick Reed делал к OTP 15, а я фиксил с каждой новой версией OTP). Этот патч не вливают потому, что фича сия может иметь далеко идущие последствия.
N>И это я не вспоминаю, что selective receive уже даёт то же самое, но дороже.
selective receive не то же самое. Хотя с помощью multiple receive markers можно воссоздать поведение нескольких каналов в одной очереди. Я не помню наверняка, но, кажется, там было какое-то ограничение все равно.
N>Нет, не сокеты.
Да именно что сокеты. Назови их "каналами", суть не поменяется. Программа должна самостоятельно открывать chan, сама должна читать из него, сама закрывать. И даже select там есть. Конечно, синтаксис и семантека поудобнее, что неудивительно — berkley sockets практически моего возраста конструкция
N>Ну вот пока эти люди будут вместо простого, эффективного, надёжного, легко управляемого и понятного использовать подобные хаки — нормальной работы не будет.
Хак там потому, что совместимость. В отличие от многих других экосистем Erlang чертовски долго сохраняет совместимость ключевых примитивов. Ибо область применения требует.
N>Такое впечатление, что упор идёт на минимизацию межнодового обмена. Может, это и ценное направление для некоторых применений, но не абсолютное.
Distribution, concurrency, fault tolerance — три кита.
N>Видимо, у них задачи другие. По сравнению с вопросом, когда же Erlang догонит конкурентов в части приоритизации, это выглядит просто мелко.
Да это вообще не проблема (за исключением детской травмы, разве что). У Erlang есть куда более реальные и насущные проблемы. Например, наличие багажа 30-летней давности. Или беда с системой типов. И вообще, современные системы пошли задом наперед, вследствие чего реальные плюшки вроде hot code load становяся костью поперек всяких там immutable containers.
Здравствуйте, SkyDance, Вы писали:
N>>"Патч по ссылке сверху" уже полтора года стоит в ожидании у моря погоды.
SD>Я же объяснил, почему. Несмотря на простоту реализации, этот подход вносит неопределенность в существующую модель, ломая базовую гарантию доставки сообщений между двумя процессами.
И я объяснил, почему и когда эта гарантия сохраняется (при отправке в одну очередь), а когда она вообще нафиг не нужна, потому что нужны как раз приоритеты. И именно это из моего ответа ты очень "художественно" выпилил.
SD> Сделать-то легко, но расхлебывать потом... за что я и люблю Erlang, 30 лет на сцене, но все еще очень конкретный и понятный.
Ну чистаа конкретный, всё такой же на 1-2 спецниши.
N>> Никакого "начиная где-то с OTP21" нет, патч уже даже не мержится.
SD>Начиная с OTP21 там есть очередь сигналов. До 21 не было, сигналы вообще не были асинхронными, что порой мешало realtime'у. Я именно про это писал, а не про патч (который, в разных формах, еще Rick Reed делал к OTP 15, а я фиксил с каждой новой версией OTP). Этот патч не вливают потому, что фича сия может иметь далеко идущие последствия.
Угу, честные очереди лучше — потому что менее костыльно.
N>>Нет, не сокеты.
SD>Да именно что сокеты. Назови их "каналами", суть не поменяется. Программа должна самостоятельно открывать chan, сама должна читать из него, сама закрывать. И даже select там есть. Конечно, синтаксис и семантека поудобнее, что неудивительно — berkley sockets практически моего возраста конструкция
Ну тогда и в Erlang "сокеты". Только создание прибито гвоздями к созданию процесса, и адресация — к процессу.
N>>Ну вот пока эти люди будут вместо простого, эффективного, надёжного, легко управляемого и понятного использовать подобные хаки — нормальной работы не будет. SD>Хак там потому, что совместимость. В отличие от многих других экосистем Erlang чертовски долго сохраняет совместимость ключевых примитивов. Ибо область применения требует.
Сохранения единственной очереди — не требует. Нормализовать — легко и быстро, даже в урезанном варианте (а тем временем продумать синтаксис и прочее).
N>>Такое впечатление, что упор идёт на минимизацию межнодового обмена. Может, это и ценное направление для некоторых применений, но не абсолютное. SD>Distribution, concurrency, fault tolerance — три кита.
N>>Видимо, у них задачи другие. По сравнению с вопросом, когда же Erlang догонит конкурентов в части приоритизации, это выглядит просто мелко.
SD>Да это вообще не проблема (за исключением детской травмы, разве что). У Erlang есть куда более реальные и насущные проблемы. Например, наличие багажа 30-летней давности. Или беда с системой типов. И вообще, современные системы пошли задом наперед, вследствие чего реальные плюшки вроде hot code load становяся костью поперек всяких там immutable containers.
У контейнеров можно мапить внешние диски. Сейчас такое работает на текущем проекте: мапится дерево из хост-системы, откуда берутся оверрайды для внутренних файловых деревьев, а если нет — применяется то, что изначально в FS контейнера. Просто и эффективно. Для Erlang помогло бы для большинства случаев relup на ходу, с небольшими внешними хелперами.
Древний багаж — так я ж про самые яркие его фичи как раз тут всё время и говорю.