Порядок формирования очереди сообщений

70 views
Skip to first unread message

Aleksey Kluchnikov

unread,
Mar 23, 2019, 7:12:52 AM3/23/19
to erlang-russian
Всем привет.
Вопрос такой, я из двух разных процессов шлю сообщение в третий процесс, причем начинаю слать сначала первое сообщение потом второе. Первое сообщение имеет размер 10 мегабайт, а втрое 1килобайт, вопрос в каком порядке они расположаться в маилбоксе 3го процесса? Первый будет который первый начал или который первый закончил отправку?

Dmytro Lytovchenko

unread,
Mar 23, 2019, 6:06:42 PM3/23/19
to Erlang по-русски
Отправитель лочит майлбокс получателя и кладёт туда копию.
Первый кто успел залочит и покладёт.
Второй затем залочит и тоже покладёт.

Max Lapshin

unread,
Mar 23, 2019, 6:07:15 PM3/23/19
to erlang-...@googlegroups.com
Посылка сообщений атомарная. Нельзя «начать посылать» сообщение

Aleksey Kluchnikov

unread,
Mar 24, 2019, 2:46:32 AM3/24/19
to erlang-russian

У меня странная ситуация, я делаю два supervisor:start_child/2 из разных процессов, один из них получает {ok, Pid}  и тут же шлю в него месадж, второй получает{error. {already_started, Pid}} и тоже тут же шлет в в этот Pid мессадж. А в этом процессе я их вижу уже в обратном порядку, то есть первым месадж умудрился сунуть процесс который получил already_started. Причем это не всегда, видимо тут рейс какой то

вс, 24 мар. 2019 г. в 01:07, Max Lapshin <max.l...@gmail.com>:
Посылка сообщений атомарная. Нельзя «начать посылать» сообщение

--
Вы получили это сообщение, поскольку подписаны на группу "Erlang по-русски".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес erlang-russia...@googlegroups.com.
Чтобы отправлять сообщения в эту группу, отправьте письмо на электронный адрес erlang-...@googlegroups.com.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

Dmitry Belyaev

unread,
Mar 24, 2019, 5:59:12 PM3/24/19
to Aleksey Kluchnikov, erlang-russian
Порядок получения сообщений от разных процессов в эрланге не гарантирован. А полагаться на детали реализации (локи и копирование) я бы не советовал.
Допустим процесс А получатель, а Б и В отправители. Даже если Б отправит сообщение А, после этого отправит сообщение В и последний отправит сообщение А, нельзя гарантированно утверждать, что сообщения от Б и В будут приняты именно в таком порядке - это детали реализации, которая может измениться.
Поэтому я бы посоветовал строить архитектуру так, чтобы порядок получения этих сообщений был не важен или чтобы они перед отправкой синхронизировались с процессом получателем.
--
Kind regards,
Dmitry Belyaev

Dmytro Lytovchenko

unread,
Mar 24, 2019, 6:58:28 PM3/24/19
to Erlang по-русски
Да здесь рейс.
Схема приблизительно такова:
1. Процесс А стартует чайлд, происходит спавн, регистрация имени, далее новый процесс выполняет свой инит, и по результату инита процесс А получит свой результат в виде пида. Выполнение инита занимает некоторое маленькое время.
2. В это время процесс Б стартует чайлд, но получает ошибку и пид, потому что регистрация уже произошла, пусть даже инит ещё и не успел выполниться.
3. Если процесс Б отправит сейчас сообщение, то он окажется первым, потому что А ещё не получил пид, который ему отдадёт, когда отработает инит.

Вот думаю как-то так.

Danil A. Zagoskin

unread,
Mar 25, 2019, 6:58:47 AM3/25/19
to Erlang по-русски
(Реализация запуска ребёнка супервизора: supervisor:handle_start_child/2)

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

А вот порядок, в котором А и Б будут обрабатывать эти ответы (читай: будут поставлены на исполнение), никто не может гарантировать, особенно в случае многопроцессорной системы (там они могут делать это одновременно),
особенно если в той же системе ещё что-то происходит, и на шедулерах ненулевые очереди.
В качестве возможного сценария:
* на время инита супервизор засыпает, поэтому новый процесс может выполняться на том же шедулере — так меньше данных гоняется туда-сюда
* после инита запущенный процесс засыпает, потому что ему больше нечего делать, и на том же шедулере может продолжить выполнение супервизор
* супервизор что-то ответил процессу А и продолжает исполняться, потому что в очереди ещё есть сообщение от Б.
* А помечается как runnable, но на том же шедулере, что и супервизор, выполняться прямо сейчас не может, поэтому начинает исполняться на другом шедулере
* супервизор ответил процессу Б и уснул, потому что больше сообщений нет
* Б может продолжить выполнение на том же шедулере, что и супервизор. На этом же шедулере свежезапущенный ребёнок.
* Б посылает сообщение новому процессу и засыпает. После этого новый процесс может сразу же начать работать на тот же шедулере (который для него родной)
В итоге получается, что А хоть и получает ответ с пидом раньше, чем Б, но может выполняться на другом шедулере, тратя время на синхронизацию и копирование сообщений между шедулерами.
Тем временем связка супервизор–Б–ребёнок может работать на одном шедулере, экономя время.
Reply all
Reply to author
Forward
0 new messages