Re[8]: Actor-based. Success story
От: vdimas Россия  
Дата: 29.06.12 11:31
Оценка:
Здравствуйте, Lazin, Вы писали:

L>С акторами очень даже возможен дедлок, в erlang-е возможен дедлок, если акторы могут ждать появления сообщений, то возможно ситуация, когда несколько акторов ждут сообщений друг от друга, но никто ничего не посылает.


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

L>Это конечно проблема архитектуры,


Я пока не понял, в чем состоит описанная тобой проблема?

L>но и в обычном многопоточном программировании deadlock это как правило проблема архитектуры.


Дедлок — это проблема сугубо синхронных операций в многопоточном окружении. Несколько синхронных алгоритмов взаимно завладели ресурсами, которые требуются для продолжения их потоков (синхронных алгоритмов), вот тебе и дедлок. У меня не хватает фантазии понять, как можно получить дедлок в асинхронной среде акторов. Можно на пальцах??? Ес-но считаем, что акторы не шарят м/у собой примитивы синхронизации, иначе зачем бы они (акторы) были нужны...


V>>Гы, ты описал простой и эффективный способ достичь банального дедлока и ничего больше. Это профанация любой асинхронности как она есть, ведь превращаешь асинхронный вызов в синхронный. Один тебе актуальный намек на эту тему: в протоколах VoIP в сигналинге бывают команды на уменьшение трафика и прочая дидагностика. Заметил как реагирует кач-во звука в Скайпе при изменении условий связи? Его протокол динамически меняет кодеки.


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


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

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


V>>Нагль малость для другого, для увеличения полезной доли в трафике. Ведь, передавая по 1-му символу с учетом всех заголовков IP и низлежащего транспорта (ethernet или ISDN), мы получаем долю полезной нагрузки менее 1%. А здесь идет речь о кол-ве вызовов АПИ ОС. Мало того, что каждый вызов ОС, даже холостой, даже на простейшем примитиве ядерной синхронизации — семафоре, занимает сотни ns на моей почти топовой машине, дык еще после самого вызова происходит некий штраф на эффективность выполнения последующего юзерского кода (добавляющий порядка 100-200ns в общем), скорее всего из-за смены контекстов виртуальной памяти туда-сюда. Т.е. эти бесполезные ~1us на сообщение предлагалось размазать на много их. За ту же стоимость 1us можно отрендерить порядка нескольких мегабайт лога в памяти, если руки правильно растут.


L>Nope, он именно для того, чтобы кол. операций ввода/вывода не соотв. 1:1 количеству сообщений. Пока устройство ввода/вывода занято — накапливаем сообщения, как только оно освободилось — пушим все что накопили, либо столькло сколько возможно спушить за один раз, а если устройство не занято и пришло одно сообщение — пушим одно сообщение.


Гы, непонимание. Нагль работает не так. В алгоритме Нагля задается некий таймаут на ожидание, обычно по-умолчанию это 200ms. Если кол-во накопленных в буфере байт меньше размера пакета, который собрался сформировать стек TCP (например, поверх ethernet это ~1400 байт), то ничего в сокет не отправляется в течении таймаута, будут ожидаться еще данные пока не пройдет таймаут или пока не хватит данных на полный пакет. Т.е. Нагль — это не объединение накопленных данных, а их ожидание. Поэтому для сигналинга Нагль обязательно отключают, ведь roundtrip при включенном нагле составляет минимум 400ms, почти пол-секунды. А при отключенном — данные отправляются мгновенно по мере готовности сокета отправлять данные.

Т.е. ошибка твоя в том, что объединение данных (записываемых в сокет пакетов) в пачки ты посчитал алгоритмом Нагля. И еще меня попытался ткнуть нгосом дважды. ))

Для TCP исходщяие данные объединяются ВСЕГДА, вне зависимости от того, включил ты для сокета опцию NO_DELAY (эта опция управляет Наглем) или нет. Они не объединяются только в том случае, если сокет отправляет пакеты быстрее, чем ты способен ему их формировать. Но это как бы и так понятно...


L>Просто если речь идет об акторах, то этот батчинг сообщений должен делаться библиотекой а не кодом актора явным образом,


Ес-но, межпотоковые очереди для диспатчинга сообщений — это сугубо инфраструктура. Но случай с логами — это вполне прикладной случай.

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


1. Нагля ты не понимаешь;
2. Принцип забора всей пачки за раз тоже не понимаешь. Эта операция ничуть не дороже забора одного сообщения, что в случае обычных мьютексов, что на lock-free очередях и CAS. Потом-то эти сообщения будут точно в таком же порядке отправлены потребителю, но с один бонусом — на каждое это сообщение уже не будет вызовов вокруг примитивов синхронизации и не будет interlocked-операций.


L>Минимизация количества ядерных вызовов это всегда благородная задача, даже в однопоточных приложениях Вообще, мысль от акоторов уже достаточно далеко уже ушла, не находишь?


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

L>Тоесть ты предлагаешь использовать ПИД регулятор для балансировки нагрузки между процессорами?


Между акторами, то бишь как потоками, так и фиберами так и приоритетом выдачи сообщений.

L>В таком случае, ты должен знать, что ПИД регулятор обычно включается в контур обратной связи,


Серьезно? )))

Исходные данные для обратной связи — это показатели диагностики, например, длина очереди сообщений к каждому актору. А регулирующие механизмы уже перечислял.

L>то бишь ты должен уметь влиять на producer-а сообщений, а тупоой bounding это как-раз и есть такая обратная связь, только вместо ПИД-регулятора у нас будет нелинейность — насыщение Вообще, конечно интересный ход мысли, никогда не думал в таком ключе о системе producer/consumer


Ну вот пробовал на де-джиттере для VoIP, сразу намного лучше чем на деджиттере с тупой пропорциональной обратной связью. Ведь интегральная составляющая в ПИД вычисляет "общий фон" то бишь общую латентность, а в случае тупого пропорционального управления этой информации нет. Далее, дифференциальная составляющая показывает текущую динамику. Т.е. можно начинать реагировать не тогда, когда очередь забита входными пакетами и их остается только дропать (для случая VoIP), а заранее. Очень удобно пользовать такую информацию для обратных связей с задержками.
Re[9]: Actor-based. Success story
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 29.06.12 16:55
Оценка: +1
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, Lazin, Вы писали:


V>Если они при этом способны обрабатывать другие сообщения, то нет никакого дедлока, это стандартный режим ожидания событий. Дедлок — это когда они блокируют друг-другу какую-либо возможность работы.

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

V>Гы, непонимание. Нагль работает не так. В алгоритме Нагля задается некий таймаут на ожидание, обычно по-умолчанию это 200ms. Если кол-во накопленных в буфере байт меньше размера пакета, который собрался сформировать стек TCP (например, поверх ethernet это ~1400 байт), то ничего в сокет не отправляется в течении таймаута, будут ожидаться еще данные пока не пройдет таймаут или пока не хватит данных на полный пакет. Т.е. Нагль — это не объединение накопленных данных, а их ожидание. Поэтому для сигналинга Нагль обязательно отключают, ведь roundtrip при включенном нагле составляет минимум 400ms, почти пол-секунды. А при отключенном — данные отправляются мгновенно по мере готовности сокета отправлять данные.


V>Т.е. ошибка твоя в том, что объединение данных (записываемых в сокет пакетов) в пачки ты посчитал алгоритмом Нагля. И еще меня попытался ткнуть нгосом дважды. ))


V>Для TCP исходщяие данные объединяются ВСЕГДА, вне зависимости от того, включил ты для сокета опцию NO_DELAY (эта опция управляет Наглем) или нет. Они не объединяются только в том случае, если сокет отправляет пакеты быстрее, чем ты способен ему их формировать. Но это как бы и так понятно...

Странно, но сам Джон Нагл не знал что его алгоритм так работает:

The solution is to inhibit the sending of new TCP segments when
new outgoing data arrives from the user if any previously
transmitted data on the connection remains unacknowledged. This
inhibition is to be unconditional; no timers, tests for size of
data received, or other conditions are required.



V>1. Нагля ты не понимаешь;

V>2. Принцип забора всей пачки за раз тоже не понимаешь. Эта операция ничуть не дороже забора одного сообщения, что в случае обычных мьютексов, что на lock-free очередях и CAS. Потом-то эти сообщения будут точно в таком же порядке отправлены потребителю, но с один бонусом — на каждое это сообщение уже не будет вызовов вокруг примитивов синхронизации и не будет interlocked-операций.
А ты не понимаешь bandwidth/latency tradeoff и capacity planning
Re[5]: Actor-based. Success story
От: vdimas Россия  
Дата: 29.06.12 17:43
Оценка: -1 :)
Здравствуйте, WolfHound, Вы писали:

WH>Да даже сообщения одного актора могут прийти не в том порядке, в котором их посылали. И это тоже race condition.


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


WH>Чтобы избавить себя от race condition нужно использовать модель каналов из сингулярити.


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


WH>Там чтобы нарваться на race condition нужно явно в коде, написать ожидание на более чем одном канале.


Если не хочется получить проблемы с надежностью, то ожидать надо на ВСЕХ каналах, на которые могут приходить сообщения. Иначе это шапкозакидательство и порчий детсад из разряда "всё будет ОК, пока мы подождем только на этом канале"...
Re[10]: Actor-based. Success story
От: vdimas Россия  
Дата: 29.06.12 19:20
Оценка:
Здравствуйте, Lazin, Вы писали:

V>>Если они при этом способны обрабатывать другие сообщения, то нет никакого дедлока, это стандартный режим ожидания событий. Дедлок — это когда они блокируют друг-другу какую-либо возможность работы.

L>Нет есть, попробуй переложить на асинхронные сообщения проблему обедающих философов и убедись сам

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

L>Странно, но сам Джон Нагл не знал что его алгоритм так работает:

L>

The solution is to inhibit the sending of new TCP segments when
L>new outgoing data arrives from the user if any previously
L>transmitted data on the connection remains unacknowledged. This
L>inhibition is to be unconditional; no timers, tests for size of
L>data received, or other conditions are required.

L>

Ну и? Это ты с одной стороны указал. А как приходит подтверждение с обратной стороны? А что есть опция fasttimo? Поищи по этому слову, в некоторых операционках этой штукой можно управлять. В сетке с быстрым roundtrip приведенный тобой отрывок никак не решает проблемы маленьких пакетов, се ля ви, её решает отложенный на 200ms (по умолчанию) ACK. Так что даже в самой быстрой сетке, при включенном Нагле, если слать короткие пакеты, то ты получишь порядка ~2.5 синхронных обмена пакетами в секунду. Если не веришь — какие проблемы поэкспериментировать и убедиться самому? При отключенном Нагле и прямых руках можно получить десятки тысяч синхронных обменов такими же маленькими пакетами в секунду.

В любом случае, даже в твоей "версии алгоритма Нагля" это и близко не то, что я предлагал делать для межпотоковых очередей. Даже если брать описание работы только одной стороны, то в алгоритме Нагля участвует размер кадра и размер окна (читать RFC-896 целиком) если данных на кадр хватает, то они отсылаются немедленно до тех пор, пока размер TCP-окна не больше текущего максимального.

Т.е. ты как бэ не понимаешь собеседника (факт налицо) и я не уверен, стоит ли дальше распинаться...
Re[9]: Actor-based. Success story
От: vdimas Россия  
Дата: 29.06.12 19:25
Оценка:
Здравствуйте, WolfHound, Вы писали:

M>>Это намек на то, что пропагандируемые тобой подходы на практике днем с огнем не.

WH>http://blogs.jetbrains.com/dotnet/2012/06/jetbrains-and-nemerle/
WH>"Core developers behind a project called Nemerle" это я, Влад и Хардкейс.

Хрена себе новость! Достойная отдельного топика. Они будут инвестировать разработку N2?

Чисто любопытство — только деньгами (переводя разработку N2 на фулл-тайм) или ресурсами тоже?
Re[10]: Actor-based. Success story
От: Jack128  
Дата: 29.06.12 19:38
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, WolfHound, Вы писали:


M>>>Это намек на то, что пропагандируемые тобой подходы на практике днем с огнем не.

WH>>http://blogs.jetbrains.com/dotnet/2012/06/jetbrains-and-nemerle/
WH>>"Core developers behind a project called Nemerle" это я, Влад и Хардкейс.

V>Хрена себе новость! Достойная отдельного топика. Они будут инвестировать разработку N2?


Ну как бе в соотвествующем форуме обсуждают: http://rsdn.ru/forum/nemerle/4789575.1.aspx
Автор: VladD2
Дата: 22.06.12
Re[9]: Actor-based. Success story
От: vdimas Россия  
Дата: 29.06.12 21:22
Оценка:
Здравствуйте, WolfHound, Вы писали:

V>>Чтобы оно сваливалось в O(N^2), надо чтобы адрес каждый раз получался минимум за O(N) и сообщение доставлялось (т.е. ресолвился адрес) тоже за O(N), где N — кол-во акторов... а так-то обе операции выполнимы за O(1).

WH>Я несколько раз явно сказал, что selective receive приводит к O(N^2) где N количество сообщений в очереди актора.

Но ты не пояснил, зачем доставать КАЖДОЕ сообщение по selective receive? Это какой-то специальный радиус кривизны рук или что? (Я уже высказывал своё мнение относительно попыток "пристроить" синхронный код в событийную модель. )

V>>Цимус в том, что нет никакого смысла посылать сообщение конкретному каналу в общем случае. Даже если в Сингулярити это на уровне языка видится именно так, реально это может происходить не так. Асинхронная отсылка может идти в общую очередь с привязанным идентификатором канала, а эта очередь затем может разгребаться на пуле потоков.

WH>Аааааааааа!
WH>Мужики всеми силами придумывали модель, которая не имеет бутылочного горлышка, а ты его искусственно создал.

Мде, приплызд... Разве перевод хендла файла в конкретный драйвер внутри дороже O(1)? Вернись выше, прочитай еще раз, что ты там утверждал. Ты фактически утверждаешь, что есть прицнипиальная разница м/у channel.send(data) и send(channel, data). Это уже какое-то нубство, сорри.

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

V>>Почему так? Предлагаю порассуждать на предмет как времени жизни каналов,

WH>Никаких проблем с этим нет. Просто убиваем канал, когда подохли оба конца и все.

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


V>>так и на предмет того, что канал вовсе не обязан иметь выделенный физический поток-обработчик сообщений.

WH>Это тоже ни разу не проблема.

Разве? Ну тогда прямо сейчас стоит остановиться и внимательно посмотреть — а точно ли идет спор о разных вещах, или кто-то не умеет формулировать свои мысли? А то как бы не было опять смешно...

Потому как балансировка нагрузки внутри ОС все-равно происходит синхронно, се ля ви. Очередь ожидания на примитивах синхронизации — она общая на все потоки/процессы и обрабатывается внутри осей синхронно. Т.е. даже если ты в памяти организуешь независимые очереди, то, ожидая ресурсы процессора на примитивах синхронизации, у тебя все-равно происходит объединение всех этих очередей ровно в одну очередь на прием к шедуллеру ОС. И здесь нет никакого бутылочного горлышка, ес-но, если диспатчить все поступающие события подряд, а не искать каждый раз "специальное". В случае приоритетных очередей и простого диспатчинга одного сообщения будет порядка K*O(x), где O(x) — стоимость операции шедуллинга в отсутствии приоритетов.

Просто я точно такой же механизм, который используется внутри оси, сделал на юзерском уровне, чтобы сократить общее кол-во ядерных примитивов синхронизации и нейтивных потоков (чем больше нейтивных потоков и примитивов синхронизации, на которых они ожидают, тем тормознутее всё работает). А так-то происходящее внутри ничем не отличалось от автобалансировки нагрузки м/у приложениями внутри ОС... А происходящее снаружи — от асинхронного ввода/вывода на сокетах (если так понятнее). Потому что модель акторов — это и есть модель ОС и независимых приложений, работающих в этой ОС и общающихся по неблокирующим линиям связи.
Re[10]: Actor-based. Success story
От: vdimas Россия  
Дата: 29.06.12 22:24
Оценка:
Здравствуйте, WolfHound, Вы писали:


V>>

V>>Например, акторы могут использовать конвейер обработки сообщений. Это означает, что в процессе обработки сообщения M1 актор может варьировать поведение, которое будет использоваться для обработки следующего сообщения. В частности, это означает, что он может начать обработку ещё одного сообщения M2 до завершения обработки M1. На том основании, что актору предоставлено право использования конвейера обработки сообщений, ещё не означает, что он этот конвейер обязан использовать. Будет ли сообщение конвейеризовано или нет — относится к задачам технического компромисса.

WH>Чем дальше, тем фееричнее.

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


WH>Если у нас обработка сообщений независима, то зачем их вообще обрабатывать одним процессом?

WH>Где смысл?

Если состояние одно общее, то вот и смысл. Простейший пример — некий прокси м/у двумя ендпоинтами или аналогичный по функциональности адаптер кодеков/протоколов и т.д. до бесконечности. Изменения состояния одного из каналов должны влиять на состояние другого (это же очевидно). И это я тебе буквально простейший пример привел, ХЗ как ты сам не додумался.

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

V>>Очень подходит к системам, где слово "протокол" не пустой звук. Самое оно.

WH>Этим системам неизмеримо лучше подходит модель сингулярити.
WH>Там протоколы описаны явно. И проверяются аж компилятором во время компиляции.

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


V>>ОМГ... Издеваешься? Рассказываю медленно... Чтобы соблюдать SRP зачастую приходится применять процесс IoC, который транзитивно ведет к последующему обязательному DI.

WH>Не приходится.

Я так понимаю, что привести подтверждающий пример проблемы составить не должно?


WH>Все дальнейшие рассуждения идут в мусор.


Это у тебя в голове мусор, рассуждаешь о том, чего не понимаешь. Нет изолированности — нет SRP, точка. ЛЮБАЯ лишняя зависимость требует поддержки в фунцкиональности. Если не требует — значит зависимости нет. Избавление от зависимостей идет через IoC и пока больше не придумали альтернативного способа даже в других парадигмах (не только ООП). Например, в ФП трюк IoC — основной и фактически единственный в проектировании после обычной процедурной декомпозиции сложности. Использование ФВП идет исключительно в сценариях IoC. Ты этим трюком пользуешь постоянно/обязательно если пишешь в ФП проекты сложнее сотен-единиц тысяч строк. Но т.к. терминологией и понятиями из области проектирования ПО не владеешь, упорствуешь на отсебятине.
Re[11]: Actor-based. Success story
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 30.06.12 06:09
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Ну и? Это ты с одной стороны указал. А как приходит подтверждение с обратной стороны? А что есть опция fasttimo? Поищи по этому слову, в некоторых операционках этой штукой можно управлять. В сетке с быстрым roundtrip приведенный тобой отрывок никак не решает проблемы маленьких пакетов, се ля ви, её решает отложенный на 200ms (по умолчанию) ACK. Так что даже в самой быстрой сетке, при включенном Нагле, если слать короткие пакеты, то ты получишь порядка ~2.5 синхронных обмена пакетами в секунду. Если не веришь — какие проблемы поэкспериментировать и убедиться самому? При отключенном Нагле и прямых руках можно получить десятки тысяч синхронных обменов такими же маленькими пакетами в секунду.

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

V>В любом случае, даже в твоей "версии алгоритма Нагля" это и близко не то, что я предлагал делать для межпотоковых очередей. Даже если брать описание работы только одной стороны, то в алгоритме Нагля участвует размер кадра и размер окна (читать RFC-896 целиком) если данных на кадр хватает, то они отсылаются немедленно до тех пор, пока размер TCP-окна не больше текущего максимального.

То, что ты предлагаешь, совсем для акторов не подходит, по причине того, что сообщения, в случае низкой нагрузки, буферизовать вовсе не нужно, задерживать их тоже нельзя, поэтому, в этом случае, батчинг должен отключаться и акторы должны тянуть сообщения из очередей по одному. Nagle это обеспечивает, а описанная тобой реализация — нет, она выльется в рост латентности и снижение общей производительности в тех случаях, когда очереди заполняются медленно.
Дальше — больше, если в нашей системе акторов есть куча переполненных очередей, то это может означать только одно — работу в режиме out of capacity. Тут нужно увеличивать capacity, либо увеличивать пропускную способность системы за счет распараллеливания тяжелых этапов обработки или использования более быстрых алгоритмов, а не уменьшать издержки на CAS-ы при чтении из очередей. Вот такой батчинг как ты описал, подходит для записи в файл, например.

V>Т.е. ты как бэ не понимаешь собеседника (факт налицо) и я не уверен, стоит ли дальше распинаться...

Если тебя не понимают, то это твои проблемы, если не можешь внятно выразить свои мысли, так, чтобы тебя поняли, то может действительно не стоит
Re[11]: Actor-based. Success story
От: WolfHound  
Дата: 30.06.12 07:25
Оценка: +1
Здравствуйте, vdimas, Вы писали:

V>Из Вики вырезка.

Да мне плевать на каком заборе это написано.

WH>>Если у нас обработка сообщений независима, то зачем их вообще обрабатывать одним процессом?

WH>>Где смысл?
V>Если состояние одно общее, то вот и смысл.
Ты что, правда не понимаешь разницы между "общим состоянием" и "независимой обработкой"?

V>Простейший пример — некий прокси м/у двумя ендпоинтами или аналогичный по функциональности адаптер кодеков/протоколов и т.д. до бесконечности. Изменения состояния одного из каналов должны влиять на состояние другого (это же очевидно). И это я тебе буквально простейший пример привел, ХЗ как ты сам не додумался.

Ох. Тут появляется состояние.
Два сообщения не могут одновременно менять состояние. Иначе состояние будет испорчено.
Значит, тебе придется упорядочить обработку этих сообщений.
И получили поток.

Максимум что можно сделать, это навернуть транзакционную память. Но даже с ней у тебя всё равно получается строгая последовательность изменений состояния.

V>Это на уровне одного канала, считай что ничего. В реальных приложениях смысла в одном процессе с одним каналом очень немного. Это только где-то на самых "концах" системы, типа асинхронного логгера. Даже сложно придумать задачу, где бы был достаточен один канал на одно приложение, кроме этого логгера... не подскажешь?

Никто не мешает проверять сколько угодно каналов одновременно в одном процессе.
Тривиальная задача.

V>>>ОМГ... Издеваешься? Рассказываю медленно... Чтобы соблюдать SRP зачастую приходится применять процесс IoC, который транзитивно ведет к последующему обязательному DI.

WH>>Не приходится.
V>Я так понимаю, что привести подтверждающий пример проблемы составить не должно?
Это ты говоришь, что без DI-контейнера SRP соблюсти нельзя.
Вот ты и доказывай.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[10]: Actor-based. Success story
От: WolfHound  
Дата: 30.06.12 07:38
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Но ты не пояснил, зачем доставать КАЖДОЕ сообщение по selective receive? Это какой-то специальный радиус кривизны рук или что? (Я уже высказывал своё мнение относительно попыток "пристроить" синхронный код в событийную модель. )

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

V>Мде, приплызд... Разве перевод хендла файла в конкретный драйвер внутри дороже O(1)? Вернись выше, прочитай еще раз, что ты там утверждал. Ты фактически утверждаешь, что есть прицнипиальная разница м/у channel.send(data) и send(channel, data). Это уже какое-то нубство, сорри.

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

V>>Цимус в том, что нет никакого смысла посылать сообщение конкретному каналу в общем случае. Даже если в Сингулярити это на уровне языка видится именно так, реально это может происходить не так. Асинхронная отсылка может идти в общую очередь с привязанным идентификатором канала, а эта очередь затем может разгребаться на пуле потоков.

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

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

Это твои больные фантазии.
Все о чем я говорю, что за этим может следить сам канал.
На самом деле каналы даже регистрировать в одном месте не нужно.
Они вполне самостоятельны.

V>>>так и на предмет того, что канал вовсе не обязан иметь выделенный физический поток-обработчик сообщений.

WH>>Это тоже ни разу не проблема.
V>Разве? Ну тогда прямо сейчас стоит остановиться и внимательно посмотреть — а точно ли идет спор о разных вещах, или кто-то не умеет формулировать свои мысли? А то как бы не было опять смешно...
Это ты не можешь понять что:
1)В акторе всегда есть логический поток. Иначе состояние актора будет порвано на куски гонками.
2)Наличие логического потока не приводит к тому, что для этого потока нужно выделять персональный поток ОС.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[12]: Actor-based. Success story
От: vdimas Россия  
Дата: 02.07.12 11:09
Оценка:
Здравствуйте, Lazin, Вы писали:

L>Я тебе процитировал оригинальный RFC. Какое отношение к обсуждаемой теме имеют детали реализации конкретного сетевого стека я не могу понять если честно.


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

V>>В любом случае, даже в твоей "версии алгоритма Нагля" это и близко не то, что я предлагал делать для межпотоковых очередей. Даже если брать описание работы только одной стороны, то в алгоритме Нагля участвует размер кадра и размер окна (читать RFC-896 целиком) если данных на кадр хватает, то они отсылаются немедленно до тех пор, пока размер TCP-окна не больше текущего максимального.

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

Я же говорю, ТЫ НИЧЕГО НЕ ПОНИМАЕШЬ. Специально сообщение никто не буферизирует. (Мне даже любопытен твой ход мыслей — а какой в этом может быть толк???)

L>задерживать их тоже нельзя,


А кто тебя спросит, можно или нельзя, если у тебя сотни-тысячи акторов и всего несколько ядер/процессоров на обработку всех задач? Курить отсюда и до обеда базовые принципы работы СМО.


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


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


L>Nagle это обеспечивает,


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

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


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

L>Дальше — больше, если в нашей системе акторов есть куча переполненных очередей, то это может означать только одно — работу в режиме out of capacity. Тут нужно увеличивать capacity, либо увеличивать пропускную способность системы за счет распараллеливания тяжелых этапов обработки


Интересно, что даст лишнее распараллеливание, если кол-во физических ядер ограничено? А оно даст только лишние тормоза. Попробуй создать несколько тысяч потоков ОС и сравни быстродействие с системой на пуле из всего нескольких потоков. Тоже получишь разницу более порядка в пользу последнего варианта, особенно если научишься дешево помещать задачи в очередь к потокам и извлекать их оттуда. Конкретное кол-во потоков зависит от характера задач. На одих задачах для моего 6-тиядерника получаю максимум на 8-ти потоках, на других — на 14-ти. В общем, никакое внутреннее зрение тебе не поможет — только эксперимент. Кстате, рекомендую покурить, для чего вообще нужны фиберы, с чем они борятся.

L>или использования более быстрых алгоритмов,


Ага, хороший лозунг, годный. "Граждане, пишите хорошие программы!"

L>а не уменьшать издержки на CAS-ы при чтении из очередей.


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

Но я тебя на всяк случай сориентирую:
— штрафы за переключения контекстов или даже за холостой вызов ядерных примитивов синхронизации — от 1us и выше на топовых процах; На нетоповых порядка 3-х и выше.
— самый "сложный" алгоритм по обработке одного сообщения тоже требует порядка 1us, обходя при этом несколько тысяч узлов алгоритма;
— большинство остальных алгоритмов имеют стоимость от единиц/дестков до сотни-другой наносекунд;
— стоимость итерации по списку сообщений без interlocked или примитивов синхронизации — порядка 1-2ns на сообщение, с этими примитивами — в 100-1000 раз дороже в пересчете на сообщение. Т.е. простое обслуживание механики сравнимо по стоимости с самыми сложными алгоритмами в системе. Почему так — предлагаю помедитировать самостоятельно. Копать в направлении отрыва внутренней пропускной способности процессоров от внешней.


L>Вот такой батчинг как ты описал, подходит для записи в файл, например.


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

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


V>>Т.е. ты как бэ не понимаешь собеседника (факт налицо) и я не уверен, стоит ли дальше распинаться...

L>Если тебя не понимают, то это твои проблемы, если не можешь внятно выразить свои мысли, так, чтобы тебя поняли, то может действительно не стоит

Уверен, коллеги всё поняли. Да и ты понял описанную технику, но споришь с ней сугубо умозрительно, не потрудившись провести и простейшего эксперимента перед этим. Еще и непониманием работы Нагля поделился. Поэтому сел в лужу минимум дважды в одном сообщении.
Re[11]: Actor-based. Success story
От: vdimas Россия  
Дата: 02.07.12 16:58
Оценка: -1 :)
Здравствуйте, WolfHound, Вы писали:

WH>Вот это твое предложение полнейший бред с алгоритмической точки зрения.

V>>>Цимус в том, что нет никакого смысла посылать сообщение конкретному каналу в общем случае. Даже если в Сингулярити это на уровне языка видится именно так, реально это может происходить не так. Асинхронная отсылка может идти в общую очередь с привязанным идентификатором канала, а эта очередь затем может разгребаться на пуле потоков.

Если уже был упомянут пул потоков, то не бред. Откуда вообще берется очередь, не хочешь прикинуть? Очередь — это то, что не может быть выполнено прямо сейчас. Поэтому у меня очередь не к агентам, а к вычислительным ресурсам. Кодирование цели — тоже разное. Иногда это текстовый адрес (для слабой связаности), где тогда ресолвинг адреса — эта требуемая часть динамического алгоритма by design. А иногда это конкретный экземпляр интерфейса получателя, в таком сценарии это ничем не отличается от асинхронного вызова делегата в другом потоке в дотнете.

WH>Ибо тебе придётся эту одну очередь разгребать в одном месте.

WH>Это и есть бутылочное горлышко.

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

WH>А все то, что ты тут понаписал, вообще к делу отношения не имеет.


Это твой пример с мейл-боксом отношения к делу не имеет, потому что кривее аналогию было бы не так просто изобрести. Если уж приводить аналогии из доставки мыла, то тут надо смотреть выше — каждый мейл-сервер — это агент, а инфраструктура интернета — среда передачи. Мейл-сервера передают друг другу сообщения по мере их поступления, безо-всякого selective receive. А то, что клиенту мейл-сервера надо выдать только его сообщения по требованию — это уже система с ограничениями, которая не может служить иллюстрацией к общему случаю. Ведь у клиента конкретного мейл-бокса свои вычислительные ресурсы, которые он пожелал состыковать на время передачи с ресурсами сервера. В агентской среде на одной физической машине сценарий прямо противоположный — клиент получает тики тогда, когда для него есть "почта", а не когда ему приспичит.


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

WH>Это твои больные фантазии.

Сам дурак.

WH>Все о чем я говорю, что за этим может следить сам канал.

WH>На самом деле каналы даже регистрировать в одном месте не нужно.
WH>Они вполне самостоятельны.

Только на слишком поверхностный взгляд. Каналы не самостоятельны ни разу. Если процесс сдох по какой-то причине, канал надо оповестить. Ну и каналу надо дать тики процессорного времени, не находишь?

V>>Разве? Ну тогда прямо сейчас стоит остановиться и внимательно посмотреть — а точно ли идет спор о разных вещах, или кто-то не умеет формулировать свои мысли? А то как бы не было опять смешно...

WH>Это ты не можешь понять что:
WH>1)В акторе всегда есть логический поток.

Наконец-то! Тебе с этого стоило начинать.

Это ты про что-то своё. Теперь я понимаю, откуда растут ноги твоего "поток прибит гвоздями к сущности". Блин, редкостная по-кривине модель. Согласен на все 100%. Потому что это на самом деле модель потока исполнения, и ничего больше, а не агента-сущности.

Понимаешь... поток исполнения не принято награждать чем-то высокоуровневым. Согласен, при попытке приписать потоку "сознание" выходит кривизна. Правильно ты тут заметил: http://www.rsdn.ru/forum/philosophy/4795688.1.aspx
Автор: WolfHound
Дата: 28.06.12
Мде, коллега, это залет.. Ты расписался что не понимаешь, что поток — это ресурс, а программная сущность — это потребитель ресурса. (Даже логический поток, а в любой ОС потоки логические ес-но). Но у тебя ресурс смешивается с потребителем... ну и каша...


WH>Иначе состояние актора будет порвано на куски гонками.


У какой-нить утилитки проброса TCP-портов такое поведение — by-design (исходники скинуть?). Её задача и состоит в умении вычислять корректное взаимное состояние 2-х независимых соединений, которые генерят события асинхронно.


WH>2)Наличие логического потока не приводит к тому, что для этого потока нужно выделять персональный поток ОС.


Да не важно. Синхронная модель заметно ограниченее асинхронной, я тут даже обсуждать не хочу. У себя я предоставил возможность создавать такие агенты, чтобы была гарантированная очередность сообщений к ним. Это полный аналог приложения [мульти-]STA (это до сих пор самая популярная модель). Для многих "линейных" задач вполне покатит...

Маршаллинг в стиле STA был сделан на сортированных буферах "внутри" самого агента. Вернее так: эта политика была реализована через агента, который является прокси к целевому, беря на себя все вопросы синхронизации. Причем, у меня было две реализации — одна через блокировки, а другая — с собственным дополнительным потоком ОС. Но это частные случаи, ес-но (дополнительному потоку надо было дать высочайший возможный приоритет.. это нормально для мультимедиа).
Re: Actor-based. Success story
От: PSV100  
Дата: 03.07.12 09:51
Оценка: 1 (1)
Здравствуйте, Буравчик, Вы писали:

Б>У кого-нибудь есть опыт участия в достаточно больших проектах, архитекутра которых была бы основана на акторах? Т.е. система разбивалась на независимые компоненты, которые обмениваются сообщениями (и только сообщениями). Конечно, вызов методов — это тоже, в некотором роде, посылка сообщений, но интересуют системы, построенные на "настоящих" сообщениях, т.е. компонент имеет очередь сообщений и явно обрабатывает их (как в Erlang).

Б>Какие языки/библиотеки использовались?
Б>Удобно ли сопровождать (понимать, расширять, изменять) такие системы?
Б>Какие есть минусы и плюсы actor-based?
Б>Для чего actor-based стоит применять, а для чего нет?
Б>Поделитесь опытом и мыслями.

Ссылки по теме, может дадут полезных мыслишек:

— модель многопоточночти в Clojure, там же есть небольшая критика модели акторов. Здесь ещё нужно учитывать потенциал для реализации в плане эффективности/производительности;

— ещё одна альтернатива: Disruptor, здесь общее описание, здесь его неплохо разобрали;

здесь есть примерчик для облегчения трассировки событий в Эрланге, когда программа строит диаграммы последовательностей (навеяно обсуждаемыми рядом ДРАКОНами и прочими схемами).
Re[12]: Actor-based. Success story
От: WolfHound  
Дата: 03.07.12 10:05
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Если уже был упомянут пул потоков, то не бред.

Полнейший берд.
Ибо в пул потоков нужно засовывать не сообщения как ты предлагаешь.
А готовые к исполнению процессы.

Но даже это плохая модель.
Гораздо эффективнее завести несколько физических потоков и создать по шедуллеру в каждом.
Каждый процесс будет знать свой текущей шедуллуер и при получении сообщения будет оповещать свой шедуллер что он готов к работе.

V>Откуда вообще берется очередь, не хочешь прикинуть? Очередь — это то, что не может быть выполнено прямо сейчас.

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

WH>>Ибо тебе придётся эту одну очередь разгребать в одном месте.

WH>>Это и есть бутылочное горлышко.
V>Так работают любые ОС. Планирование ресурсов — всегда централизованное.
Это твои фантазии.

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

Ох. Ты даже деревьев не видишь.
На листиках зациклился.

V>Это твой пример с мейл-боксом отношения к делу не имеет, потому что кривее аналогию было бы не так просто изобрести.

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

V>Только на слишком поверхностный взгляд. Каналы не самостоятельны ни разу. Если процесс сдох по какой-то причине, канал надо оповестить.

Умирающий процесс, который держит конец канала и оповестит.
Если он последний, то он и убьёт ставший никому не нужным канал.
Тоже мне бином Ньютона.

V>Ну и каналу надо дать тики процессорного времени, не находишь?

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

WH>>1)В акторе всегда есть логический поток.

V>Наконец-то! Тебе с этого стоило начинать.
Я с этого и начал. Уже которое сообщение это тебе повторяю.

V>Это ты про что-то своё.

Нет. Я это про модель акторов.

V>Теперь я понимаю, откуда растут ноги твоего "поток прибит гвоздями к сущности". Блин, редкостная по-кривине модель. Согласен на все 100%. Потому что это на самом деле модель потока исполнения, и ничего больше, а не агента-сущности.

У каждого актора есть свой поток.
Всегда.
Ибо у актора есть состояние.
Обработка каждого сообщения использует и в некоторых случаях меняет это состояние.
Обработка сообщения всегда должна видеть согласованное состояние. Те читать и писать одновременно нельзя.
Две обработки сообщения не могут менять состояние одновременно.
Таким образом, у нас возникает логическая последовательность, в которой происходит обработка сообщений.
Это и есть поток.
rwlock'и, транзакции итп это уже оптимизации. И к модели отношения не имеют.

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

V>Понимаешь... поток исполнения не принято награждать чем-то высокоуровневым. Согласен, при попытке приписать потоку "сознание" выходит кривизна. Правильно ты тут заметил: http://www.rsdn.ru/forum/philosophy/4795688.1.aspx
Автор: WolfHound
Дата: 28.06.12
Мде, коллега, это залет.. Ты расписался что не понимаешь, что поток — это ресурс, а программная сущность — это потребитель ресурса. (Даже логический поток, а в любой ОС потоки логические ес-но). Но у тебя ресурс смешивается с потребителем... ну и каша...

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

V>У какой-нить утилитки проброса TCP-портов такое поведение — by-design (исходники скинуть?). Её задача и состоит в умении вычислять корректное взаимное состояние 2-х независимых соединений, которые генерят события асинхронно.

Заводим по процессу на соединение и вперед.
Не забывай, что есть не только пальмы, но и ёлки.

V>Маршаллинг в стиле STA был сделан на сортированных буферах "внутри" самого агента. Вернее так: эта политика была реализована через агента, который является прокси к целевому, беря на себя все вопросы синхронизации. Причем, у меня было две реализации — одна через блокировки, а другая — с собственным дополнительным потоком ОС. Но это частные случаи, ес-но (дополнительному потоку надо было дать высочайший возможный приоритет.. это нормально для мультимедиа).

Какой феерический бред с алгоритмической точки зрения.
И после такого ты еще набираешься наглости учить других.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Actor-based. Success story
От: mima  
Дата: 03.07.12 13:35
Оценка: 9 (3)
Здравствуйте, Буравчик, Вы писали:

Б>У кого-нибудь есть опыт участия в достаточно больших проектах, архитекутра которых была бы основана на акторах? Т.е. система разбивалась на независимые компоненты, которые обмениваются сообщениями (и только сообщениями). Конечно, вызов методов — это тоже, в некотором роде, посылка сообщений, но интересуют системы, построенные на "настоящих" сообщениях, т.е. компонент имеет очередь сообщений и явно обрабатывает их (как в Erlang).


Не сильно большая система, примерно 5 разных программ, запущенных на нескольких серверах, общающихся друг с другом. 3 из них содержат разной степени сложности иерархию акторов, 2 другие — клиенты с примитивными акторами-слушателями. Есть и другие программы — части этой системы, но они не actor-based, поэтому не упоминаю.

Б>Какие языки/библиотеки использовались?


Scala/Akka.

Б>Удобно ли сопровождать (понимать, расширять, изменять) такие системы?


Ожидания оправдались. К сожалению, в то время когда всё это писалось у Akka не было durable mailboxes, потом написать свой диспетчер было сложновато, поэтому некоторые части реализованы не так идеально как хотелось бы. Но даже тогда таких пунктиков было мало, сразу находились нужные вещи: супервайзеры, лоадбалансеры, роутеры, пулы акторов, ActorRegistry, лёгкое подключение remote-акторов и много чего ещё реализовано и готово к работе.

С помощью actor-based подхода легко писать модульно, поэтому пишешь более модульно. Из-за этого, кроме облегчения в поддержке, мы смогли легко нарастить доп. функциональность, которая сильно облегчила нам работу. Её бы просто не было, если бы не было принято решение о разбиении системы на столь мелкие при обычной разработке части. Хотя это косвенная заслуга actor-based.

Понимать систему просто, если знаешь иерархию — лучше иметь рисунок. Сами акторы простые, пишешь их как можно более иммутабельными и быстрыми. Т.к. работают они по сути в одном потоке, и данные свои меняют тоже в одном, то с concurrency проблем нет. Хотя обдумывать их lifecycle надо, но это один раз: let it crash работает.

Расширять/изменять — зависит от. Если код одного актора править, или даже нескольких — то это обычно очень быстро и просто. Если иерархию, то напряжения больше, но это делается гораздо реже. Есть чёткое разделение между иерархией и "рабочими" акторами.

Б>Какие есть минусы и плюсы actor-based?


Слишком общий вопрос, пропущу.

Б>Для чего actor-based стоит применять, а для чего нет?


Мало смысла, если пишешь однопоточную монолитную систему: например, десктопная программка, которой ничего не надо вычислять в фоне.

В нашем случае система должна была быть модульной, просто в силу задачи, должна уметь шариться по разным машинам, быть масштабируемой, внутри модулей код должен быть параллельным. Тут actor-based напрашивался.

Б>Поделитесь опытом и мыслями.


Ну вот, вкратце.
Re[12]: Actor-based. Success story
От: vdimas Россия  
Дата: 04.07.12 22:09
Оценка: :)
Здравствуйте, WolfHound, Вы писали:

WH>Значит, тебе придется упорядочить обработку этих сообщений.

WH>И получили поток.

Если нужно поток, можно взять STA-like апартмент. Только они дорогие, хотя местами это оправдано/удобно (особенно когда какой-то задаче надо дать специальные приоритеты на уровне ОС, тогда нужно сопоставить задаче поток уровня ОС).

WH>Максимум что можно сделать, это навернуть транзакционную память. Но даже с ней у тебя всё равно получается строгая последовательность изменений состояния.


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

V>>Это на уровне одного канала, считай что ничего. В реальных приложениях смысла в одном процессе с одним каналом очень немного. Это только где-то на самых "концах" системы, типа асинхронного логгера. Даже сложно придумать задачу, где бы был достаточен один канал на одно приложение, кроме этого логгера... не подскажешь?

WH>Никто не мешает проверять сколько угодно каналов одновременно в одном процессе.
WH>Тривиальная задача.

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

Кароч, мне как раз по работе приходится все эти сценарии из всевозможных позиций иметь. Приходится и как ты сказал (через poll/select списка дескрипторов) и как я рекомендую — в чистом асинхронном виде. Твой сценарий — самый неудобный и немасштабируемый. Как пример — в сети есть сравнительные данны по замерам libevent в различных режимах. На предложенной тобой технике-аналоге poll//select масштабируемость никакая и, начиная с определенного кол-ва дескрипторов, это всё настольуо безбожно сливает асинхронным решениям, что мне лень это дале обсуждать, сорри.

Твоё мнения я услышал. Оно противоречит данным мн-ва экспериментов. Обсуждение для меня закончено.


V>>Я так понимаю, что привести подтверждающий пример проблемы составить не должно?

WH>Это ты говоришь, что без DI-контейнера SRP соблюсти нельзя.
WH>Вот ты и доказывай.

Нет, я утверждал, что ты путаешь DI-процесс и DI-контейнер, завтавляя меня отвечать на утверждения, которые я не делал. Еще я утверждал, что качественное SRP недостижимо без трюка IoC, а любое IoC потом компенсируется DI-процессами — это by design и это не перепрыгнуть никак. Короче, я хз зачем ты вообще решил спорить по этой теме.
Re[13]: Actor-based. Success story
От: vdimas Россия  
Дата: 04.07.12 22:50
Оценка: :)
Здравствуйте, WolfHound, Вы писали:

WH>Ибо в пул потоков нужно засовывать не сообщения как ты предлагаешь.

WH>А готовые к исполнению процессы.

Покажи на пальцах или псевдокоде в каком порядке их туда засовывать и почему именно так?

WH>Но даже это плохая модель.

WH>Гораздо эффективнее завести несколько физических потоков и создать по шедуллеру в каждом.
WH>Каждый процесс будет знать свой текущей шедуллуер и при получении сообщения будет оповещать свой шедуллер что он готов к работе.

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


V>>Откуда вообще берется очередь, не хочешь прикинуть? Очередь — это то, что не может быть выполнено прямо сейчас.

WH>Очередь в данном контексте это логический примитив общения между строго одним производителем и строго одним потребителем. Реализующий политику доставки первый пришёл первый ушёл.
WH>Все остальное детали реализации.

Это не ответ на вопрос — почему вообще образуется очередь. Попробуй еще раз. Если что — освежи предмет СМО перед ответом... Ах да... там же ненавистный матан... Тогда прими мои соболезнования.


WH>>>Ибо тебе придётся эту одну очередь разгребать в одном месте.

WH>>>Это и есть бутылочное горлышко.
V>>Так работают любые ОС. Планирование ресурсов — всегда централизованное.
WH>Это твои фантазии.

Гы, так даже не в курсе, как всё работает? )))

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

WH>Ох. Ты даже деревьев не видишь.
WH>На листиках зациклился.

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

V>>Это твой пример с мейл-боксом отношения к делу не имеет, потому что кривее аналогию было бы не так просто изобрести.

WH>Ох.
WH>Терминологией не владеешь.

??? Терминологией мейл-боксов? )))

WH>Почтовый ящик это логический примитив общения между множеством производителей и строго одним потребителем. Порядок доставки сообщений не определен.


Всё ясно. Тот момент, что клиент мейл-бокса и мейл-сервер в общем случае имеют независимые вычислительные ресурсы, ты таки не понял. ЧТД.


V>>Только на слишком поверхностный взгляд. Каналы не самостоятельны ни разу. Если процесс сдох по какой-то причине, канал надо оповестить.

WH>Умирающий процесс, который держит конец канала и оповестит.

Не оповестит при аварийном выходе.

WH>Если он последний, то он и убьёт ставший никому не нужным канал.


Это только в песочницах возможно... в которых сферокони пасутся.


V>>Ну и каналу надо дать тики процессорного времени, не находишь?

WH>Это совсем бред. Канал штука совершенно пассивная. И процессорные тики получает от того кто этот канал дергает в тот момент когда его дергают.

Ну и! Тебе же совсем немного осталось для понимания, сделай усилие. Это же не синхронный вызов метода в том же потоке, когда вызывающий "отдает" свой ресурс на время исполнения вызываемого метода. Нелья же явно получить тики от другого потока. Сейчас доходит?


WH>>>1)В акторе всегда есть логический поток.

V>>Наконец-то! Тебе с этого стоило начинать.
WH>Я с этого и начал. Уже которое сообщение это тебе повторяю.

V>>Это ты про что-то своё.

WH>Нет. Я это про модель акторов.

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


V>>Теперь я понимаю, откуда растут ноги твоего "поток прибит гвоздями к сущности". Блин, редкостная по-кривине модель. Согласен на все 100%. Потому что это на самом деле модель потока исполнения, и ничего больше, а не агента-сущности.

WH>У каждого актора есть свой поток.
WH>Всегда.
WH>Ибо у актора есть состояние.

Да поняли мы уже, что ты путаешь поток исполнения с атомарностью операций.

WH>Обработка каждого сообщения использует и в некоторых случаях меняет это состояние.

WH>Обработка сообщения всегда должна видеть согласованное состояние. Те читать и писать одновременно нельзя.

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


WH>Две обработки сообщения не могут менять состояние одновременно.


Могут, потому что у состояния есть многомерное пространство.

WH>Таким образом, у нас возникает логическая последовательность, в которой происходит обработка сообщений.


В STA возникает. Иначе — исходим из асинхронности. Агент по твоей модели будет глуп до невозможности. Ему даже нельзя будет отменить какую-нить тяжеловесную операцию... Ведь он их исполняет сугубо последовательно. Это то, почему STA непопулярно — оно провоцирует на глупый код.


WH>Это и есть поток.


Разве что поток сознания... Я уже в растерянности.. то ли ты настолько далек от совремнной многопоточности, то ли настолько сварился в собственном соку, что твоя терминология изменила свою начальную семантику. Хотя, судя по плаванию вокруг DI — похоже на оба фактора вместе.

WH>rwlock'и, транзакции итп это уже оптимизации. И к модели отношения не имеют.


Транзакции — это не оптимизации, а условия существования апартментов, отличных от STA. Это уровень дизайна.

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


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

WH>Ибо есть ОС в которых потоки ОС можно плодить в любых количествах без проблем с производительностью.

WH>Например, та же сингулярити может создавать и шуделлить процессы в любом количестве. Ибо там не используется аппаратная защита и шедуллеры ОС могут сидеть на каждом аппаратном потоке и шедуллить не хуже чем твои юзермоде шедуллеры которыми ты так гордишься.

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

WH>И никто не мешает создать свою сингулярити внутри одного процесса винды.


Ну так создай и позамеряй, какие проблемы?


V>>У какой-нить утилитки проброса TCP-портов такое поведение — by-design (исходники скинуть?). Её задача и состоит в умении вычислять корректное взаимное состояние 2-х независимых соединений, которые генерят события асинхронно.

WH>Заводим по процессу на соединение и вперед.

И еще третий, обслуживать взаимное состояние этих двух. Садись, два.

WH>Не забывай, что есть не только пальмы, но и ёлки.


Много пил?


V>>Маршаллинг в стиле STA был сделан на сортированных буферах "внутри" самого агента. Вернее так: эта политика была реализована через агента, который является прокси к целевому, беря на себя все вопросы синхронизации. Причем, у меня было две реализации — одна через блокировки, а другая — с собственным дополнительным потоком ОС. Но это частные случаи, ес-но (дополнительному потоку надо было дать высочайший возможный приоритет.. это нормально для мультимедиа).

WH>Какой феерический бред с алгоритмической точки зрения.
WH>И после такого ты еще набираешься наглости учить других.

(1) Как всегда 0 аргументов.
(2) Забываешь перед прочтением влючать процессор.
(2-a) В скорее всего просто не в теме и кидаешь сугубо умозрительные понты.

Попытаюсь тебя сосредоточить на сути решения: никто в здравом уме не будет делать выделенный STA-поток посто так. Зачем так было сделано — в абзаце написано. Буфер с сортировкой для мультимедиа обязателен. Специальный приоритет на "нейтивном" потоке ОС — тоже.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.