Re[13]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 12:19
Оценка: +2 :))) :)
Здравствуйте, LaPerouse, Вы писали:

BZ>>для человека, следующего ра развитием ЯП и знающего десятки языков начиная с фортрана и лиспа

LP>Череп не жмет?

мы точно на rsdn? в разделе философия программирования?
Люди, я люблю вас! Будьте бдительны!!!
Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 14:05
Оценка: 46 (5)
Речь идет разумеется не о том, что концепция акторов сама по себе является антипаттерном только потому, что это акторы, а о случаях их неправильного использования или чрезмерного использования. Проблема однако в том, что по моим наблюдениям 90 процентов случаев их реального применения на практике являются чрезмерными или неправильными. На волне популярности эрланга и всевозможных фреймворков навроде akka, концепция акторов сама по себе переоценена и выглядит в глазах некоторых как серебряная пуля, хотя и близко таковой не является. Приведу некоторые примеры, с которыми столкнулся за последние два года.

1. Использование акторов для parallel execution.

actor = new Actor();
actor.sendMessage(new CalculateSomething(1, 2, 3));
//Все, здесь ничего больше не делается, и если даже этот код
//является частью другого актора, в 99 процентах случаях он либо не
//получает других сообщений кроме CalculationResult,
//а если и получает, то ничего не может с ними сделать без CalculationResult


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

actor = new Actor();
actor.sendMessage(new CalculateSomething(1, 2, 3));
someHardCalculation();


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

actor = new Actor();
actor.sendMessage(new CalculateSomething(1, 2, 3));
actor.sendMessage(new CalculateSomething(4, 5, 6));
calc = someHardCalculation();


которое выполнится последовательно с первым вычислением (используется один актор). Потом приходится переписывать такой код с помощью Conditions или Future:

calc = new Calculator();
calc1Future = calc.calculate(1, 2, 3);
calc2Future = calc.calculate(4, 5, 6);
calc = someHardCalculation();
result = resultCalculation(calc, calc1Future.get(), calc2Future.get());


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

2. В предыдущем примере речь шла о явно ошибочном использовании акторов. Однако даже в тех случаях, когда использование акторов, казалось бы, оправдано, я бы 10 раз подумал, прежде чем их использовать. Приведу типичный пример — сервер, работающий по TCP, большое количество параллельных сессий, но время обработки запроса незначительное. Казалось бы, что может быть проще

sessionLock.lock();
try {
    commonDataLock.lock();
    try {
        //Непродолжительная обработка
        executeLogic(message, session, commonData);
    } finally {
      commonDataLock.unlock();
    }
} {
  sessionLock.unlock();
}


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

3. Асинхронный код сложнее в поддержке, это все знают. Однако асинхронность асинхронности рознь. Одно дело, когда это асинхронный вызов с callback-ом, сохраняющий контекст вызова. И другое дело — актор, который каждый раз в момент прихода сообщения должен понять, в каком он состоянии находится. Городить на каждый чих FSM — удовольствие не из приятных. При добавлении одной дополнительной коммуникации или одного дополнительного контекста количество состояний способно комбинаторно взорваться. Бизнес-логика размазывается по всему коду актора на маленькие порции. Вместо одного сервисного метода вы ползаете по функциям перехода, проклиная автора за то, что тот не оставил excel-таблицу с описанием автомата. Это в том случае, если автор удосужился оформить актор именно в виде автомата с именованным признаком состояния, а не определяет контекст из лапши условий — последнее встречается чаще, тогда приходится брать бумагу и карандаш и рисовать граф с переходами, чтобы составить хотя бы приблизительное представление о том, что же делает эта мешанина кода. Спору нет, в некоторых случаях такой подход может быть эффективным с точки зрения производительности — в случае с TCP-сервером из предыдущего примера применение нескольких типов акторов может быть оправданным в случае достаточно тяжелых запросов. Однако в любом случае, прежде чем браться за акторы, я бы посмотрел на другие способы решения задачи. Например, shared memory что бы про него не говорили при соблюдении простейших правил и правильного проектирования совершенно безопасен, а код ясен и читаем. Акторы же, даже в тех случаях, когда их применение технически оправдано, принципиально тяжелы для восприятия — это их фунадментальная особенность в силу того, что каждый актор является машиной состояний.

activateState1();
actor1.sendMessage(new Request1(data1));
actor2.sendMessage(new Request2(data2));
state = STATE1_WAIT_FOR_RESPONSE1_RESPONSE2;


void response1Handler(Response1 resp) {
     this.resp1 = resp;
     if (state == STATE1_WAIT_FOR_RESPONSE1_RESPONSE2) {
         state = STATE1_WAIT_FOR_RESPONSE2;
     } else if (state == STATE1_WAIT_FOR_RESPONSE1){
       process(this.resp1, this.resp2);
       someCommonForState1State2Processing();
       state = STATE1_PROCESSED;
     } else if (state == STATE2_WAIT_FOR_RESPONSE1) {
       //Здесь другой контекст (STATE2) и совершенно другое вычисление
       doAnotherProcessing(this.resp1);
       someCommonForState1State2Processing();
       state = STATE2_PROCESSED;
     } else if (...){}//Обработка других комбинаций
}

void response2Handler(Response2 resp) {
     this.resp2 = resp;
     if (state == STATE1_WAIT_FOR_RESPONSE1_RESPONSE2) {
         state = STATE1_WAIT_FOR_RESPONSE1;
     } else if (state == STATE1_WAIT_RESPONSE2) {
       process(this.resp1, this.resp2);
       someCommonForState1State2Processing();
       state = STATE1_PROCESSED;
     }
}


Что может произойти с кодом выше при добавлении нового контекста STATE3 знает любой, кто хоть немного знаком с конечными автоматами — произойдет взрыв состояний — STATE12_WAIT_RESPONSE1_RESPONSE2, STATE23_WAIT_FOR_RESPONSE1_RESPONSE2 и т.д. Ситуацию может облегчить использование иерархических автоматов — тогда вместо подобной комбинации состояний будет дерево и состояния WAIT_FOR_RESPONSE1_RESPONSE2 будут дочерними по отношению к контекстам STATE1, STATE2, STATE3... Но иерархические автоматы никто в подобных случаях не использует (уже спасибо, если удосужились оформить машину состояний в виде обычного автомата), потому что для этого требуются либо дополнительные телодвижения, либо дополнительная библиотека. Также количество состояний можно сократить с использованием coroutines (в С# — yield return), но они не в каждом языке есть и не каждому разработчику знакомы. А акторы, черт возьми, знакомы уже многим (к сожалению).

Что касается технической стороны кода, приведенного выше, то он может быть оправдан в тех случаях, когда помимо Response1 и Response2 актор ожидает например еще SomeMessage, обработкой которого он потенциально может заняться, ожидая ответа на Request1 и Request2. Но анализ встретившихся мне случаев опять-таки говорит о том, что в большинстве случае никаких других сообщений кроме Response1 и Response2 актор не принимает (а если и принимает, то не может ничего сделать с ними без Response1 и Response2), и висит в спинлоке или мьютексе точно также, как висел бы в случае явной блокировки:

ProcessingResult process(data1, data2) {
      future1 = performer1.request(new Request1(data1));
      future2 = performer2.request(new Request2(data2));
      return process(future1.get(), future2.get());
}

ProcessingResult2 processAnother(data) {
      return performer1.request(new Request1(data));
}


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

Если заменить 95 процентов всех случаев использования акторов на shared memory/future/stm/однопоточный код, получится технически как минимум эквивалентное (а с учетом первого пункта о неправильным использовании — зачастую и превосходящее) решение, к тому же значительно выигрывающее по ясности и поддерживаемости. Из этого не следует, что акторы не нужны, но рядовому программисту они почти не нужны, объективно. Само собой, я не затрагиваю тех, кто пишет ПО для кластеров — в этой области это де-факто стандарт коммуникации.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[7]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 10:53
Оценка: 5 (1) +1
Здравствуйте, LaPerouse, Вы писали:

LP>Как без корутин сделать такой код


вообще есть три варианта реализации асинхронности:

1. stackless coroutines — синтаксический сахар в языке, который разворачивается в конечный автомат при компиляции
2. stackful coroutines — каким-то способом выделяется множество стеков (alloca, fibers и т.д.) и переключение между ними осуществляется вручную. этот способ часто может быть реализован на чисто библиотечном уровне, док-во этого — соответствующие библиотеки Boost
3. green threads — это stackful coroutines с регулярным автоматическим переключением между ними, реализованным в VM. ruby/erlang делают это через определённое кол-во шагов интерпретации, ghc — при выделении очередного блока памяти (а память в single-assignment языках выделяется постоянно)
Люди, я люблю вас! Будьте бдительны!!!
Re[18]: Об очередном антипаттерне. Модель акторов.
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 26.08.15 10:50
Оценка: 1 (1) +1
Здравствуйте, Sinix, Вы писали:

I>>Скорее всего бОльшая часть программ тупо перестанет работать, потому что stackfull, внезапно, дает возможность, ну например, повторно войти в принципиально нереэнтерабельный участок кода.

S>Так это не столько к await, сколько ко всему коду, написанному без учёта реэнтерабельности.
S>Ну, т.е. поломается и без await-а

Поломается из за применения любой stackfull короутины, действительно, без разницы, с await или без. Причина именно в стекфулл короутине, она вводит ничем не ограниченую кооперативную многозадачность. Однозадачный код вдруг станет многозадачным.
Реэнтерабельность в нереэнтерабельный участок это частный случай. Куда более вероятен сбой из за нарушения инварианта/протокола любого глобального ресурса, хотя бы и простой переменной.
Re[10]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 23:00
Оценка: :))
Здравствуйте, alex_public, Вы писали:


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


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


_>Конечно. Только непонятно какое это всё имеет отношение к модели акторов. Вот скажем подобный C++ код:


Какой-то странный у вас С++ код, я такой никогда не видел (лямбды, замыкания...). Я работаю все больше с легаси-кодом, который надо допилить для интеграции с нашим ява-софтом и видеть замыкания в С++ для меня не менее странно, чем айфон в пирамиде Хеопса.

_>[ccode]

_>1. Это модель акторов или нет?

Нет

_>2. Используется по делу или нет?


Да

_>3. Сложный и неудобный код или нет?


Нет

_>И он действительно будет внешне покороче. Но удобнее ли с помощью него понимать, что там действительно происходит?


Одинаково понятно, если сделать скидку на странный С++. Также понятно, что приведенный пример никакого отношения не имеет к тому, о чем я писал.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[9]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 12:02
Оценка: +2
Здравствуйте, LaPerouse, Вы писали:

LP>>>Как без корутин сделать такой код

BZ>>3. green threads — это stackful coroutines
LP>То есть coroutines. Чтд.

и? мне кажется, ты на каких-то базвордах зациклился, тогда как мир не ограничивается C#

BZ>>с регулярным автоматическим переключением между ними, реализованным в VM. ruby/erlang делают это через определённое кол-во шагов интерпретации, ghc — при выделении очередного блока памяти (а память в single-assignment языках выделяется постоянно)


LP>Тут нужно переключать не абы когда (как в случае c green threads в общем случае), а именно после отправки асинхронного сообщения, и возвращать управление после получения ответа на запрос.


насколоько я понимаю, переключать нужно при ожидании ответа — если он ещё не готов. опять же советую тебе глядеть на green thread как разновдиность потоков вообще, просто более эффективно реализуемую. а ты похоже всё пытаешься к своему миру C# свести, отсюда трудности
Люди, я люблю вас! Будьте бдительны!!!
Re[15]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 12:31
Оценка: +2
Здравствуйте, LaPerouse, Вы писали:

LP>У балаболов всегда все легко и просто.


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

LP>И виртуальную машину с сопрограммами они за денек сделают,


было дело, я пока был в отпуске, сообразил как сделать сопрограммы на setjmp (а мне их в C страшно не хватало!), потом приехал залез в справку по борланду и там в статье по setjmp написано — их можно использовать для сопрограмм. так что это вполне штатная фича была и библиотеку я позже таки сделал
Люди, я люблю вас! Будьте бдительны!!!
Re[12]: Об очередном антипаттерне. Модель акторов.
От: Sinix  
Дата: 26.08.15 08:23
Оценка: +2
Здравствуйте, LaPerouse, Вы писали:


S>>Разумеется, это не значит, что на голый await стоит натягивать акторы.

LP>В Unity3d натянули на yield return null. Правда, не акторы, а автоматный код скриптов.
Угу, это не совсем акторы.

Акторы предполагают, во-первых, декларативное описание ч/з комбинацию состояние-входы-выходы.
Во-вторых, свою модель вычислений (с immutable-данными + pure-функциями).
Во-третьих, полноценный рантайм для шедулинга/обработки ошибок/отката/etc.
В четвёртых, прозрачное масштабирование от мобильника до облака.

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

А, да, всю эту кухню конечно можно спрятать за await, но менее главной она от этого не станет.
Re[19]: Об очередном антипаттерне. Модель акторов.
От: neFormal Россия  
Дата: 26.08.15 20:04
Оценка: +2
Здравствуйте, Sinix, Вы писали:

S>И на эту тему лучше реальных эрланговодов поспрашивать, я скорее свечку держал

S>Если ничего не перепутал, из отметившихся в ветке, это как минимум Mamut.

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

F>>я погуглил, но там что-то совсем мутное.

F>>можешь найти адекватный пример?
S>Неа, про эрланг на андроиде с чужих слов, гугль находит что-то типа такого, не больше.

да, видел. но мне показалось мутным.
много чего запускали на андроиде на разных языках, но всё оно, как по мне, выглядит слабо.
...coding for chaos...
Re[15]: Об очередном антипаттерне. Модель акторов.
От: neFormal Россия  
Дата: 28.08.15 21:56
Оценка: +2
Здравствуйте, LaPerouse, Вы писали:

LP>До такой степени не имеет, что _любой_ актор является конечным автоматом просто по определению.


обоснования?
актор может не менять поведение в зависимости от состояния и при этом оставаться актором. а может и состояния не менять.

LP>Приведу пример, приближенный к реальному, — рассмотрим два актора, первый — комната для онлайн игры, второй — игра в комнате. Комната может остановить игру путем посылки сообщения игре StopGame и получит в ответ от игры после остановки GameStopped. При этом игра может остановиться сама по себе (например, игру покинули все игроки или просто нашелся победитель). В этом случае GameStopped придет по событию остановки игры, без всякого запроса StopGame со стороны комнаты. Эти случае должны быть обработаны совершенно различным способом, потому что в случае остановки игры по инициативе комнаты комната должна после получения сообщения GameStopped разослать системные сообщения о принудительной остановке игры и произвести запись в лог (ибо это не характерная ситуация — игроки не смогли доигать до конца).


во всех случаях достаточно сказать серверу ойвсё(успешно/ниочинь, результаты);

LP>В случае самостоятельной остановки игры комната просто удалит игру.


игра удаляется в любом случае.

LP>Рассмотрим две причины — удаление комнаты (очевидно, перед удалением игра в ней должна быть остановлена) и остановку сервера (сервер рассылает всем комнатам сообщения деинициализации). Обработка сообщения GameStopped зависит от причины остановки! Если остановка игры была вызвана удалением комнаты, необходимо после получения подтверждения об остановке игры и записей в лог подготовить комнату к удалению и послать сообщение серверу, что комната готова к удалению.

LP>В случае остановки сервера нужно просто произвести деинициализацию.

во всех случаях достаточно облить бензином и поджечь.

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


почему тогда у тебя получается так сложно?
...coding for chaos...
Re[18]: Об очередном антипаттерне. Модель акторов.
От: Mamut Швеция http://dmitriid.com
Дата: 26.08.15 18:49
Оценка: 38 (1)
F>т.е. эрланговские акторы без gen_event'а уже не акторы?

Акторы, акторы.

Главное отличие Эрланга — прагматичный подход. Если теория говорит, что «функциональный язык должен быть чистым», а «акторы должны декларативно задаваться», Эрланг смотрит на это с легким недоумением и презрением, а потом реализует то, что наиболее рпактично в реальном мире.



В итоге да, наверное, чисто с академической точки зрения Эрланг и не шибко функциональный, и не шибко акторный, и не шибко ОО, и... и...

F>я погуглил, но там что-то совсем мутное.

F>можешь найти адекватный пример?

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


dmitriid.comGitHubLinkedIn
Re[15]: Об очередном антипаттерне. Модель акторов.
От: so5team https://stiffstream.com
Дата: 21.01.16 13:13
Оценка: 15 (1)
Здравствуйте, LaPerouse, Вы писали:

LP>Другая известная в мире С++ реализация акторов SObjectizer также использует конечные автоматы для реализации акторов.


Кстати говоря, намедни в SObjectizer появилась поддержка иерархических конечных автоматов. Появлению этой функциональности в немалой степени поспособствовало именно это обсуждение. Так что спасибо за поднятую тему
Re: Об очередном антипаттерне. Модель акторов.
От: Alex912  
Дата: 24.08.15 14:46
Оценка: 6 (1)
Здравствуйте, LaPerouse, Вы писали:

Этож старо как мир.
https://www.chrisstucchio.com/blog/2013/actors_vs_futures.html

Actors are awesome. But they aren't the only abstraction we have. Futures are another great abstraction which work very well with purely functional code. Actors are great for maintaining state, futures are great for everything else.

Re[6]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 20:33
Оценка: 5 (1)
Здравствуйте, -MyXa-, Вы писали:

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


LP>>А что, планируют добавить? Не слышал ни разу. Вообще говоря, мне их откровенно не хватает.


MX>Я тоже не слышал. Но представьте, если правда добавят! Это будет революция в программировании!


Бросай этот балаган.
При помощи нормально реализованных сопрограмм можно сильно сократить код КА, избавившись от самой назойливой и мусорной части. Я как-то очень давно при помощи этой библиотеки урезал код автомата читающего с ком-порта раза эдак в три.
Опять же, в Unreal Engine и Unity сопрограммы уже давно используются для программирования логики. Надо думать, гейм-девелоперы, которым чаще других приходится работать с КА, не зря их используют.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[6]: Корутины в C#
От: LaPerouse  
Дата: 24.08.15 21:40
Оценка: 5 (1)
Здравствуйте, -MyXa-, Вы писали:

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


Q>>Здравствуйте, -MyXa-, Вы писали:


MX>>>А в С# корутины не годятся (они без стека) — весь код придётся переписывать.


Q>>Почему это не годятся? В C# есть и корутины через yield return, и async/await. Какого именно стека им не хватает?


MX>Ты-ж сам ответил на свой вопрос — потому, что надо расставить async и await в стратегических местах. А если Майкрософт её слово придумают — тоже будем его по всему коду расставлять?


Ты так говоришь, как будто это что-то плохое (С)
Все равно код с await будет непринужденно работать с синхронной реализацией. Какие проблемы написать два слова?
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[11]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 17:18
Оценка: 5 (1)
Здравствуйте, Sinix, Вы писали:

S>Разумеется, это не значит, что на голый await стоит натягивать акторы.


Вот рассмотрим актор Player (игрок) и два варианта реализации.
В виде классического КА:

if (state == MONITORING_STATE) {
    if (enemy.getPosition().distance(player.getPosition()) < OBSERVATION_DISTANCE) {
        state = APPROACH_TO_ENEMY;
        player.MoveTo(directionToEnemy...);
    }
} else if (state == APPROACH_TO_ENEMY) {
    player.MoveTo(directionToEnemy...);
    if (enemy.getPosition().distance(player.getPosition()) < ATTACK_DISTANCE)
        state = ATTACK_STATE;
} else if (state == ATTACK_STATE) {
    //..Фаза атаки (за один фрейм)
}


С поддержкой сопрограмм код становится линейным

if (enemy.getPosition().distance(player.getPosition() < OBSERVATION_DISTANCE) {
    while (enemy.getPosition().distance(player.getPosition() > ATTACK_DISTANCE) {
        player.MoveTo(directionToEnemy...);//Смещение в направлении врага на расстояние, которое может быть пройдено за один фрейм
        yield return null;
    }
    attack(enemy, player);//Начинается атака, которая ТОЖЕ может быть записана в виде ЛИНЕЙНОГО кода
}


Как можно видеть конечный автомат при помощи сопрограмм реализован без введения трех явных состояний. При этом он вполне может оставаться конечным автоматом, то есть у него могут быть другие состояния. Просто число этих состояний можно резко уменьшить, а код сделать линейным и понятным. Повторюсь, я с помощью сопрограмм резко уменьшил при помощи одной ява-библиотеки код конечного автомата, сделав его четким и понятным.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[16]: Об очередном антипаттерне. Модель акторов.
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 26.08.15 10:09
Оценка: 5 (1)
Здравствуйте, alex_public, Вы писали:

_>Здесь имелось в виду что-то рукопашное, типа примеров в первом сообщение темки. А async/await из C# — это всё же сопрограмма, а не конечный автомат (пусть даже она и реализована через него внутри). Собственно если мы например переделаем в следующей версии C# реализацию async/await через stackfull coroutine, то скорее всего никто этого и не заметит. )))


Скорее всего бОльшая часть программ тупо перестанет работать, потому что stackfull, внезапно, дает возможность, ну например, повторно войти в принципиально нереэнтерабельный участок кода. Ну вот блокирующее чтение из стрима. Глобальные ресурсы пока еще никто не отменял. Опаньки !
Отредактировано 26.08.2015 10:46 Pauel . Предыдущая версия .
Re[3]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 24.08.15 18:46
Оценка: +1
Здравствуйте, LaPerouse, Вы писали:

LP>Я пишу на java и С++, здесь нет никаких корутин и вообще мало кто из разработчиков даже представляет об этом концепте. Есть решения для java, основанные на потоках (тяжелы и не применимы в production), есть на модифицкации байткода, я даже использовал как-то одну такую библиотеку для написания одного сложного КА, но в мире java и С++ это именно что исключение.


В C++ сопрограммы есть уже давным давно. Уже даже в Boost включены не первый год. А сейчас обсуждается вообще добавление в стандарт языка. )))
Re[6]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 19:09
Оценка: -1
Здравствуйте, alex_public, Вы писали:

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


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


Сопрограмма — это обычный иерархический конечный автомат, в котором состояние автоматически управляется компилятором/рантаймом.

_>И ничего страшного в конечных автоматах тоже нет, особенно если пользоваться удобными готовыми реализациями (например как из того же boost'a).


Пример из исходного сообщени видел? Если их прудумывают на ровном месте, привнося совершенно ненужную сложность, ничего хорошего в них нет.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re: Об очередном антипаттерне. Модель акторов.
От: Mamut Швеция http://dmitriid.com
Дата: 24.08.15 20:27
Оценка: :)
Практически все описаные антипаттерны возникают из отсутсвия в языке и среде нативной поддержки собственно модели акторов. Отсюда все эти стенания о спинлоках, задержке сообщений и прочем и прочем. Это не говоря уже об отсутствии необходимой инфраструктуры, следящей за завершением исполнения процессов, изоляции процессов и многого другого. Откуда проистекают стенания о невозможности следить за акторами с «богатым состоянием» и т.п.


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


dmitriid.comGitHubLinkedIn
Re[10]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 11:20
Оценка: :)
Здравствуйте, BulatZiganshin, Вы писали:

BZ>а генерация конечных автомтов — это как рах экзотика, реализованная только в C#. я лично о ней впервые услышал несколько месяцев назад, когда стал изучать пропозалы C++


Просто открываем любой C# проект — код будет усыпан yield return и async-ами. В С++ проектах редко можно встретить применение сопрограмм. Так что есть экзотика?
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[10]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 12:14
Оценка: :)
Здравствуйте, BulatZiganshin, Вы писали:

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


LP>>>>Как без корутин сделать такой код

BZ>>>3. green threads — это stackful coroutines
LP>>То есть coroutines. Чтд.
BZ>и? мне кажется, ты на каких-то базвордах зациклился, тогда как мир не ограничивается C#

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

BZ>>>с регулярным автоматическим переключением между ними, реализованным в VM. ruby/erlang делают это через определённое кол-во шагов интерпретации, ghc — при выделении очередного блока памяти (а память в single-assignment языках выделяется постоянно)

LP>>Тут нужно переключать не абы когда (как в случае c green threads в общем случае), а именно после отправки асинхронного сообщения, и возвращать управление после получения ответа на запрос.
BZ>насколоько я понимаю, переключать нужно при ожидании ответа — если он ещё не готов. опять же советую тебе глядеть на green thread как разновдиность потоков вообще, просто более эффективно реализуемую.

Чем это отличается это от того, что я написал? И с чего ты взял, что в эрланге все происходит именно так? Вон Мамут, который в отличие от тебя писал на эрланге, ничего подобного не приводит.

BZ>а ты похоже всё пытаешься к своему миру C# свести, отсюда трудности


К моему? Ну-ну. Я никогда не писал и ни планирую писать на С# и ссылаюсь на него лишь потому, что именно этот язык ввел понятия сопрограмм в мейнстрим и для многим именно мс-ская реализация является референсной.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[14]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 12:22
Оценка: -1
Здравствуйте, BulatZiganshin, Вы писали:

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


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


BZ>как я уже говорил, есть во первых вариант с потоками/файберами и т.п. во вторых, для любого компилируемого языка (без VM) можно сделать крошечную ассемблерную библиотечку, которая создаёт и переключает стёки. а для языка с VM такое моджно сделать на уровне VM, а наружу выставить в виде API


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

BZ>твоя проблема в том что ты не знаешь ничего кроме своего C# и начинаешь рассуждать о других языках


Ты про erlang и про зеленые потоки точно также узнал, как и про то, что я пишу на С#?
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[13]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 14:50
Оценка: -1
Здравствуйте, LaPerouse, Вы писали:

LP>>>Ключевые тезисы: иерархический конечный автомат, уменьшение количества состояний автомата за счет автоматического запоминания текущей позиции в стеке


BZ>>вау! а почему бы не называть это просто сопрограммами, благо что этот термин применятся аж с 60-х?


LP>Потому что нужно объяснить человеку, как сопрограммы помогают в реализации конечного автомата за счет уменьшения количества состояний. Которое достигается путем запоминания текущей позиции в стеке.


так он говорит "Если мне надо реализовать конечный автомат...". а ты в ответ ему говоришь о том как реализовывать "иерархический конечный автомат" — термин который ты сам только что придумал. более того, такие сопрограммы вовсе недоступны в C#. и что ты ему докажешь? что отсутствующие в C# stackful сопрограммы нельзя реализовать автоматами
Люди, я люблю вас! Будьте бдительны!!!
Re[11]: Об очередном антипаттерне. Модель акторов.
От: Mamut Швеция http://dmitriid.com
Дата: 25.08.15 15:18
Оценка: +1
LP>Чем это отличается это от того, что я написал? И с чего ты взял, что в эрланге все происходит именно так? Вон Мамут, который в отличие от тебя писал на эрланге, ничего подобного не приводит.

Взял он с того, что он, в отличие от тебя, знает, о чем говорит. И что я не приводил? Из двух строчек моего кода ты сделал далеко идущие выводы о том, что где когда и как переключается?

1. В Эрланге именно зеленые потоки, а не корутины, что бы ты там себе не нафантазировал. В Эрланге они называются процессами.
2. Процессы управляются планировщиками задач (по умолчанию — по одному на каждое ядро, но это настраиваемо)
3. Каждому процессу выделяется X редукций, где редукция — это посылка сообщения, вызов функции и т.п. После каждого сообщения вызова функции X уменьшается. Когда он достигает 0, процесс перемещается в конец очереди процессов, ожидающих обработку. Количество редукций тоже настраиваемо
4. Все переключения делаются прозрачно для самой программы. Стоимость переключения — какой-то незаметный никому мизер, в районе μs
5. Процесс, ожидающий получение сообщения вообще не потребляет CPU, потому что какой-либо код в нем выполнится только после того, как он получит сообщение
6. Переключение на другой процесс (а в вырожденных случаях — перенос процесса на другое ядро CPU) может произойти в любой момент практически любой точки кода, и произойдет незаметно для программы.


dmitriid.comGitHubLinkedIn
Re[11]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 25.08.15 15:21
Оценка: +1
Здравствуйте, LaPerouse, Вы писали:

LP>Мда... Собственно, на это можно прекращать дискуссию, поскольку ты вообще не представляешь себе предмет обсуждения.

LP>Ключевые тезисы: иерархический конечный автомат, уменьшение количества состояний автомата за счет автоматического запоминания текущей позиции в стеке

Конечно не представляю. ))) Я же не расставляю конечные автоматы по всему коду и по любому поводу.

Вот скажем тот последний пример из первого сообщения реализуется на акторах в пару строк очевидного кода. Но мы вместо этого накрутим страшный конечный автомат на полстраницы и потом побежим на форум рассказывать про плохие акторы, которые приводят к такому дикому коду. )))
Re[13]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 15:43
Оценка: +1
Здравствуйте, LaPerouse, Вы писали:

LP>Значит, либо Булат фантазер


ты бы хоть на мой профиль поглядел

LP>либо уровень владения тобой предметом (эрланг) оставляет желать лучшего.


мне неудобно говорить за мамута, но возможно он просто поленился повторять то, что мы уже 386 раз здесь обсуждали. в разрезе и эрланга, и хаскеля, и акторов, и бустовских библиотек. но теперь он подробно описал модель, по которой green threads реализовывается во всех языках, и в clr/jvm если соберутся — сделают также. других вариантов нет
Люди, я люблю вас! Будьте бдительны!!!
Отредактировано 25.08.2015 15:56 BulatZiganshin . Предыдущая версия . Еще …
Отредактировано 25.08.2015 15:54 BulatZiganshin . Предыдущая версия .
Re[10]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 19:28
Оценка: +1
Здравствуйте, alex_public, Вы писали:

BZ>>первый поток обходит каталоги читает входные файлы

BZ>>второй поток разбивает эти данные на сжимаемые куски
BZ>>пул потоков выполняют задания на сжатие
BZ>>потоки из того же пула выполняют задания на шифрование
BZ>>послежний поток пишет готовые блоки в архив
BZ>>соответственно реализовывается всё это графом сообщений, часть задач распараллеливается в пуле потоков, часть ограничена скоростью I/O и может работать через любые асинхронные средства

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


нет, думаю это вообще два разных вопроса. первое — это модель переключения между потоками исполнения: потоки ОС, зелёные потоки, сопрограммы двух видов. второе — это модель их взаимодействия: акторы, графы данных, разделяемая память. соответственно, пул потоков — это лишь механизм параллельного вполнения, а акторы или графы данных прекрасно могут работать поврех них как и любого другого механизма
Люди, я люблю вас! Будьте бдительны!!!
Re[15]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 25.08.15 23:52
Оценка: +1
Здравствуйте, BulatZiganshin, Вы писали:

_>>1. Конечные автоматы. Предлагаю исключить их из нашей дискуссии, т.к. в данной темке есть кажется только один человек, которые предпочитает реализовывать многопоточность/асинхронность с их помощью. И это не я и не ты (вроде бы).

BZ>этот человек — MS. ты похоже не в курсе async/await в c# и msvc2015

Здесь имелось в виду что-то рукопашное, типа примеров в первом сообщение темки. А async/await из C# — это всё же сопрограмма, а не конечный автомат (пусть даже она и реализована через него внутри). Собственно если мы например переделаем в следующей версии C# реализацию async/await через stackfull coroutine, то скорее всего никто этого и не заметит. )))
Re[13]: Об очередном антипаттерне. Модель акторов.
От: so5team https://stiffstream.com
Дата: 26.08.15 07:37
Оценка: +1
Здравствуйте, LaPerouse, Вы писали:

LP>Actor:

LP>
LP>if (state == 1) {
LP>    fsmState = WAIT_FOR_RESPONSE1;
LP>    call(request1);
LP>}
LP>else if (state == 2) {
LP>    fsmState = WAIT_FOR_RESPONSE2;
LP>    call(request2);
LP>}

LP>//Обработка
LP>void messageReceived(Response response) {
LP>    if (fsmState == WAIT_FOR_RESPONSE1)
LP>        calc1(response);
LP>    else if (fsmState == WAIT_FOR_RESPONSE2)
LP>        calc2(response);
LP>    else if (fsmState == NO_REQUEST)//здесь сообщение Response пришло без Request
LP>        processEvent(response);
LP>}
LP>


Может быть вовсе и не так. А вот так:
// Описание связей.
fsmState.in(WAIT_FOR_RESPONSE1).event(calc1);
fsmState.in(WAIT_FOR_RESPONSE2).event(calc2);
fsmState.in(NO_REQUEST).event(processEvent);


Т.е. обслуживание конечного автомата актора является одной из задач фреймворка, реализующего Actor Model. То, что в Akka/Scala этого нет не означает ущербности ActorModel.
Отредактировано 26.08.2015 7:39 so5team . Предыдущая версия .
Re[21]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 26.08.15 13:27
Оценка: -1
Здравствуйте, Ikemefula, Вы писали:

I>Правильно — как только вводится второй поток или вторая задача, вся стройная концепция быстро рушится.


ты потерял суть спора
Люди, я люблю вас! Будьте бдительны!!!
Re[22]: Об очередном антипаттерне. Модель акторов.
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 26.08.15 13:57
Оценка: +1
Здравствуйте, BulatZiganshin, Вы писали:

I>>Правильно — как только вводится второй поток или вторая задача, вся стройная концепция быстро рушится.


BZ>ты потерял суть спора


Цитирую: "для этого нужно чтобы прикладной код ещё и заходил туда"

Смотри внимательно, прикладной код быть в обеих ветках, в разное время, но не в обеих одновременно
var oldState = globalResource;
globalResource = new State();
var x = stream.read();  /// вот этот вызов сделаем неблокирующим, шоб сильнее было
... ля-ля-ля
globalResource = oldState;

где то "там"

var oldState = globalResource;
globalResource = new State();
var x = someLongBlockingCall();
... ля-ля-ля
globalResource = oldState;


Теперь, если стрим будет неблокирующим, прикладной код может работать одновременно в обеих ветках.
Re[15]: Об очередном антипаттерне. Модель акторов.
От: so5team https://stiffstream.com
Дата: 29.08.15 06:36
Оценка: +1
Здравствуйте, LaPerouse, Вы писали:

S>>Т.е. обслуживание конечного автомата актора является одной из задач фреймворка, реализующего Actor Model. То, что в Akka/Scala этого нет не означает ущербности ActorModel.


LP>В акка как раз это есть.


Можете показать?

LP> Только конечный автомат как его не украшай, останется конечным автоматом.


КА есть КА и применение КА не всегда уместно. Как и попытки заменить КА сопрограмами. Только это вовсе не означает, что Actor Model является антипатерном.

LP> Если бы накладные расходы от КА можно было бы нивелировать красивым фреймворком, весь геймдев не двигался бы от КА к behaviour tree и сопрограммам.


Аргумент из категории "миллионы мух..."
Re[15]: Об очередном антипаттерне. Модель акторов.
От: Mamut Швеция http://dmitriid.com
Дата: 29.08.15 07:45
Оценка: +1
LP>Это что касается теории. На практике _каждая_ известная мне реализация акторов имеет в своем составе ДСЛ для определения конечного автомата
LP>Вот для AKKA:
LP>http://doc.akka.io/docs/akka/snapshot/scala/fsm.html

1. Какие тебе реализации акторов известны?
2. fsm в akka напрямую взят из библиотеки Erlang'а, потому что создание конечных автоматов является часто встречающейся задачей, и для нее в Erlang'е сделано общее решение. Так же в эрланге есть общие решения для серверов, событий и супервизоров: потому что это — часто встречающиеся паттерны, и почему бы не реализовать что-то, часто встречающееся.

И да, (gen_)fsm — самый редко используемых из всех.


dmitriid.comGitHubLinkedIn
Re[15]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 31.08.15 07:51
Оценка: +1
Здравствуйте, LaPerouse, Вы писали:

_>>Конечный автомат — это полезный инструмент, но не имеющий никакого отношения к вопросам многопоточности, асинхронного кода, сопрограммам и т.п. )

LP>До такой степени не имеет, что _любой_ актор является конечным автоматом просто по определению.

Смотрю сюда https://ru.wikipedia.org/wiki/%D0%9C%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D0%B0%D0%BA%D1%82%D0%BE%D1%80%D0%BE%D0%B2 и не вижу ничего подобного.

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

LP>Итак, имеем:
LP>1. Актор имеет состояние
LP>2. Актор принимает входные символы (сообщения)
LP>3. При поступлении сообщения актор переходит в новое состояние, которое зависит от поступившего сообщения и текущего состояния

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

LP>Если заменить в этих пунктах слово "актор" на "конечный автомат", получим букварное определение КА.


Вот вот, это собственно оно и есть. ))) Только опять же непонятно причём тут вообще акторы? )

LP>Это что касается теории. На практике _каждая_ известная мне реализация акторов имеет в своем составе ДСЛ для определения конечного автомата

LP>Вот для AKKA:
LP>http://doc.akka.io/docs/akka/snapshot/scala/fsm.html

Библиотека boost имеет в своём составе DSL для реализации конечного автомата. Означает ли это, что любое приложение с использованием boost'a должно включать в себя конечный автомат? )

LP>Я пробовал разные DSL для описания конечных автоматов. В java их вагон. Однако, другие разработчики,как это не странно, были не в восторге от этих фреймворков. Уверяю тебя, для человека, который будет поддерживать код, который ты привел, изначальная форма при всей ее уродливости намного понятнее. Испробовано несколько раз.


Вообще то в данном коде главное не используемый DSL (мне так просто удобнее было записывать), а выкидывание ненужных состояний, введённых для демонстрации неудобства модели акторов. )))

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

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


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

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

Ты тут сравниваешь реализацию случая 1 на future с реализацией случая 2 на акторах и делаешь вывод о более удобном коде на future? Смешно. Давай поглядим что будет, если играть по честному.

Если сравнивать реализации для случая 1, то я уже привёл примеры соответствующих акторов. Как видно, они имеют одинаковый объём кода и читаемость с реализацией на future. И незачем придумывать тут какие-то "любые сообщения, которые могут переводить актор в различные состояния" — их нет по условию задачи.

Если же сравнивать реализации для случая 2, то они безусловно становятся сложнее. Но я легко приведу их тебе. Правда только после того, как увижу твою реализацию данного случая на future. Т.е. когда параллельно с твоим кодом "process(future1.get(), future2.get());" должен выполняться ещё какой-то код, причём меняющий состояние системы так, что должен меняться результат обработки.

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


Да, уже хорошо видно, что у тебя все выводы основаны на впечатлениях из твоего уютненького маленького мирка. В котором, если уж используют актор, то исключительно огромные, с десятками входных сообщений. Но не стоит думать, что и весь мир устроен точно так же. )
Re[2]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 14:58
Оценка:
Здравствуйте, Alex912, Вы писали:

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


A>Этож старо как мир.

A>https://www.chrisstucchio.com/blog/2013/actors_vs_futures.html

A>

A>Actors are awesome. But they aren't the only abstraction we have. Futures are another great abstraction which work very well with purely functional code. Actors are great for maintaining state, futures are great for everything else.


За ссылку спасибо. Но хоть и старо, но судя по тому что я видел, их начали использовать совершенно бездумно, прямо как синглтон пятнадцать лет назад.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re: Об очередном антипаттерне. Модель акторов.
От: -MyXa- Россия  
Дата: 24.08.15 18:10
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>3. Асинхронный код сложнее в поддержке, это все знают.


Я предлагаю отказаться от выражения "асинхронный код", разделив его на два — "лапшеобразный код" и "асинхронная логика".

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

Если код использует полиморфизм (например, как в iostreams, IStream (это из COM) или даже С-шный minizip), то его логика может выполняться асинхронно. Например, двадцать лет назад был написан и скомпилирован, а после компиляции безвозвратно потерян вот этот блокирующий (псевдо)код:

result read_from_stream(stream s)
{
    while(s.is_good())
    {
        s.read();
    };
    return result(...);
}


Понятное дело, что пока не прочитается весь поток (а это может занять хоть неделю), мы не сможем обрабатывать другие запросы. Правда? Конечно нет! Достаточно запустить эту функцию внутри корутины, передав такой stream, который в своей функции read не будет дожидаться окончания чтения, а вместо этого только быстренько запустит чтение и сразу же yield-нется на корутине. Через неделю, когда чтение закончится, нужно не забыть переключиться обратно в корутину, чтобы продолжить выполнение с того места, где мы прервались в прошлый раз.

Теперь только остаётся отказаться от выражения "блокирующий код", т.к. оно вовсе лишено смысла (выше я применил его, чтобы было легче читать. Это помогло?).
Если не поможет, будем действовать током... 600 Вольт (C)
Re[2]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 18:18
Оценка:
Здравствуйте, -MyXa-, Вы писали:

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


MX>Теперь только остаётся отказаться от выражения "блокирующий код", т.к. оно вовсе лишено смысла (выше я применил его, чтобы было легче читать. Это помогло?).


Ты наверное невнимательно прочитал мое сообщение. Процитирую

Ситуацию может облегчить использование иерархических автоматов — тогда вместо подобной комбинации состояний будет дерево и состояния WAIT_FOR_RESPONSE1_RESPONSE2 будут дочерними по отношению к контекстам STATE1, STATE2, STATE3... Но иерархические автоматы никто в подобных случаях не использует (уже спасибо, если удосужились оформить машину состояний в виде обычного автомата), потому что для этого требуются либо дополнительные телодвижения, либо дополнительная библиотека. Также количество состояний можно сократить с использованием coroutines (в С# — yield return), но они не в каждом языке есть и не каждому разработчику знакомы. А акторы, черт возьми, знакомы уже многим (к сожалению).


Я пишу на java и С++, здесь нет никаких корутин и вообще мало кто из разработчиков даже представляет об этом концепте. Есть решения для java, основанные на потоках (тяжелы и не применимы в production), есть на модифицкации байткода, я даже использовал как-то одну такую библиотеку для написания одного сложного КА, но в мире java и С++ это именно что исключение.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[4]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 18:53
Оценка:
Здравствуйте, alex_public, Вы писали:

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


LP>>Я пишу на java и С++, здесь нет никаких корутин и вообще мало кто из разработчиков даже представляет об этом концепте. Есть решения для java, основанные на потоках (тяжелы и не применимы в production), есть на модифицкации байткода, я даже использовал как-то одну такую библиотеку для написания одного сложного КА, но в мире java и С++ это именно что исключение.


_>В C++ сопрограммы есть уже давным давно. Уже даже в Boost включены не первый год. А сейчас обсуждается вообще добавление в стандарт языка. )))


Неужели? К сожалению, программисты, которые на С++ пишут, не в курсе этого. Иначе я бы не смотрел сейчас на конечный автомат с over 2000 строк кода. Мне периодически приходится сталкиваться с С++ кодом, иногда даже приходится немного писать на нем, ни разу не сталкивался с этим концептом.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[3]: Об очередном антипаттерне. Модель акторов.
От: -MyXa- Россия  
Дата: 24.08.15 18:58
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>Я пишу на java и С++, здесь нет никаких корутин и вообще мало кто из разработчиков даже представляет об этом концепте. Есть решения для java, основанные на потоках (тяжелы и не применимы в production), есть на модифицкации байткода, я даже использовал как-то одну такую библиотеку для написания одного сложного КА, но в мире java и С++ это именно что исключение.


Я старался про стратегию рассказать — чтобы было видно, так сказать, куда стремиться, а не про тактику. Вот в Java добавят корутины со стеком, а мы уже будем знать — зачем это. А в С# корутины не годятся (они без стека) — весь код придётся переписывать.
Если не поможет, будем действовать током... 600 Вольт (C)
Re[5]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 24.08.15 19:04
Оценка:
Здравствуйте, LaPerouse, Вы писали:

_>>В C++ сопрограммы есть уже давным давно. Уже даже в Boost включены не первый год. А сейчас обсуждается вообще добавление в стандарт языка. )))

LP>Неужели? К сожалению, программисты, которые на С++ пишут, не в курсе этого. Иначе я бы не смотрел сейчас на конечный автомат с over 2000 строк кода. Мне периодически приходится сталкиваться с С++ кодом, иногда даже приходится немного писать на нем, ни разу не сталкивался с этим концептом.

Более того, к примеру на этом форуме многие нюансы с работой сопрограмм в C++ разбирались, несколько лет назад. )

Что касается конечного автомата, то у него есть отдельная ценность, никак не связная с задачами эмуляции сопрограмм. И ничего страшного в конечных автоматах тоже нет, особенно если пользоваться удобными готовыми реализациями (например как из того же boost'a).
Re[4]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 19:16
Оценка:
Здравствуйте, -MyXa-, Вы писали:

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


LP>>Я пишу на java и С++, здесь нет никаких корутин и вообще мало кто из разработчиков даже представляет об этом концепте. Есть решения для java, основанные на потоках (тяжелы и не применимы в production), есть на модифицкации байткода, я даже использовал как-то одну такую библиотеку для написания одного сложного КА, но в мире java и С++ это именно что исключение.


MX>Я старался про стратегию рассказать — чтобы было видно, так сказать, куда стремиться, а не про тактику. Вот в Java добавят корутины со стеком, а мы уже будем знать — зачем это. А в С# корутины не годятся (они без стека) — весь код придётся переписывать.


А что, планируют добавить? Не слышал ни разу. Вообще говоря, мне их откровенно не хватает.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[4]: Корутины в C#
От: Qbit86 Кипр
Дата: 24.08.15 19:59
Оценка:
Здравствуйте, -MyXa-, Вы писали:

MX>А в С# корутины не годятся (они без стека) — весь код придётся переписывать.


Почему это не годятся? В C# есть и корутины через yield return, и async/await. Какого именно стека им не хватает?
Глаза у меня добрые, но рубашка — смирительная!
Re[5]: Об очередном антипаттерне. Модель акторов.
От: -MyXa- Россия  
Дата: 24.08.15 20:04
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>А что, планируют добавить? Не слышал ни разу. Вообще говоря, мне их откровенно не хватает.


Я тоже не слышал. Но представьте, если правда добавят! Это будет революция в программировании!
Если не поможет, будем действовать током... 600 Вольт (C)
Re[7]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 24.08.15 20:22
Оценка:
Здравствуйте, LaPerouse, Вы писали:

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

LP>Сопрограмма — это обычный иерархический конечный автомат, в котором состояние автоматически управляется компилятором/рантаймом.

Это безстековые) А у сопрограммы со стеком получается совсем другой расклад. Да, и кстати, скажем на той же винде они доступны давным давно для любых языков программирования (которые могут работать с win api). Но реализация в языке (пусть даже и в виде библиотеки, как в boost'e) конечно же удобнее, т.к. там всякие специфические нюансы (типа проброса исключений) можно учесть.

_>>И ничего страшного в конечных автоматах тоже нет, особенно если пользоваться удобными готовыми реализациями (например как из того же boost'a).

LP>Пример из исходного сообщени видел? Если их прудумывают на ровном месте, привнося совершенно ненужную сложность, ничего хорошего в них нет.

Ну естественно можно устроить говнокод и с помощью идеальных инструментов. Однако если применять конечные автоматы по делу, да ещё и в правильном виде (скажем таком http://www.boost.org/doc/libs/develop/libs/msm/doc/HTML/ch03s04.html#d0e1462), то они намного улучшают качество кода.
Re[5]: Корутины в C#
От: -MyXa- Россия  
Дата: 24.08.15 20:23
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Здравствуйте, -MyXa-, Вы писали:


MX>>А в С# корутины не годятся (они без стека) — весь код придётся переписывать.


Q>Почему это не годятся? В C# есть и корутины через yield return, и async/await. Какого именно стека им не хватает?


Ты-ж сам ответил на свой вопрос — потому, что надо расставить async и await в стратегических местах. А если Майкрософт её слово придумают — тоже будем его по всему коду расставлять? В предыдущем
Автор: -MyXa-
Дата: 24.08.15
сообщении я писал, что корутины со стеком не требуют модификации запускаемого кода (в т.ч. типа возвращаемого значения). На этом форуме про это был уже сра обсуждение.
Если не поможет, будем действовать током... 600 Вольт (C)
Re[5]: Корутины в C#
От: alex_public  
Дата: 24.08.15 20:27
Оценка:
Здравствуйте, Qbit86, Вы писали:

MX>>А в С# корутины не годятся (они без стека) — весь код придётся переписывать.

Q>Почему это не годятся? В C# есть и корутины через yield return, и async/await. Какого именно стека им не хватает?

Это не верная формулировка. Правильная такая: в C# генераторы (yield) и выпрямление (эмуляция синхронного вида) асинхронного кода (async/await) реализованы с помощью безстековых сопрограмм (которые по сути являются конечными автоматами, генерируемыми компилятором), не идущими ни в какое сравнение с нормальными сопрограммами со стеком (которые по сути являются полноценным аналогом потоков, только с кооперативной многозадачностью и мгновенным (без путешествий в ядро ОС) переключением).
Re[2]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 21:04
Оценка:
Здравствуйте, Mamut, Вы писали:

M>В том же Erlang'е практически все описанные «проблемы» давно, по сути, решены и описываются во первых же строках любой книги по Erlang'у. Курить те же деревья супервизоров.


Ну, начнем с того, что у меня не erlang, а jvm или c++. И как минимум там это действительно выглядит как антипаттерн. Про erlang ничего сказать не могу, не читал, не использовал, не сталкивался. Но с эрлангом или без, от конечного автомата все равно не убежите. Другое дело, он может быть замаскирован корутинами или продожениями. Но в любом случае будет интересно увидеть, что же так сказать эрланг животворящий делает. Как будет выглядеть на эрланге приведенный мной пример (с Response1 и Response2)?
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[8]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 21:34
Оценка:
Здравствуйте, alex_public, Вы писали:

_>>>И ничего страшного в конечных автоматах тоже нет, особенно если пользоваться удобными готовыми реализациями (например как из того же boost'a).

LP>>Пример из исходного сообщени видел? Если их прудумывают на ровном месте, привнося совершенно ненужную сложность, ничего хорошего в них нет.
_>Ну естественно можно устроить говнокод и с помощью идеальных инструментов. Однако если применять конечные автоматы по делу, да ещё и в правильном виде

С этим как бы никто и не спорит. Но если можно обойтись без состояния вообще, или с маленьким количеством состояний, а вместо этого городят большой автомат, то соответственно, такой автомат хуже, чем его отсутствие.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[9]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 24.08.15 22:41
Оценка:
Здравствуйте, LaPerouse, Вы писали:

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


Конечно. Только непонятно какое это всё имеет отношение к модели акторов. Вот скажем подобный C++ код:
void OnClick()
{
    thread([url=UrlCtrl.GetText()]{
        PostMessage(DownloadData(url)); //PostMessage - функция из используемой gui библиотеки
    }).detach();
}
void OnData(Data d)
{
    OutputCtrl.SetText(d);
}


1. Это модель акторов или нет?
2. Используется по делу или нет?
3. Сложный и неудобный код или нет?

Да, конечно, я легко могу на том же C++ с помощью сахара сопрограмм преобразовать этот же код к чему-то вроде:
void OnClick() async
(
    OutputCtrl.SetText(await([url=UrlCtrl.GetText()]{return DownloadData(url);})); //async и await - обёртки над сопрограммой/созданием потока
)


И он действительно будет внешне покороче. Но удобнее ли с помощью него понимать, что там действительно происходит?
Re[11]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 24.08.15 23:31
Оценка:
Здравствуйте, LaPerouse, Вы писали:

_>>1. Это модель акторов или нет?

LP>Нет

Почему? )

_>>И он действительно будет внешне покороче. Но удобнее ли с помощью него понимать, что там действительно происходит?

LP>Одинаково понятно, если сделать скидку на странный С++.

Если одинаково, то может тогда и не стоит добавлять сопрограммы? ) Тогда тот же async/await из C# не имеет особого смысла? )

LP>Также понятно, что приведенный пример никакого отношения не имеет к тому, о чем я писал.


Хм, а разве есть какое-то принципиальное отличие этого моего примера и данного кода
actor = new Actor();
actor.sendMessage(new CalculateSomething(1, 2, 3));
someHardCalculation();

из пункта номер 1 изначального сообщения темки? ) Заменяем CalculateSomething на DownloadData, a someHardCalculation на "обработка следующих сообщений в очереди (GUI приложения)"...
Re[7]: Корутины в C#
От: -MyXa- Россия  
Дата: 25.08.15 06:13
Оценка:
Здравствуйте, LaPerouse, Вы писали:

MX>>Ты-ж сам ответил на свой вопрос — потому, что надо расставить async и await в стратегических местах. А если Майкрософт её слово придумают — тоже будем его по всему коду расставлять?


LP>Ты так говоришь, как будто это что-то плохое (С)

LP>Все равно код с await будет непринужденно работать с синхронной реализацией. Какие проблемы написать два слова?

Какие были проблемы использовать ISequentialStream в C#, что понадобилось сделать монструозный (десять страниц одних оглавлений... ) System.IO.Stream?

Я думаю, и у твоего вопроса, и у моего один ответ. Но давай не будем о грустном. Зачем нам чужие проблемы?

З.Ы. Я в C# ничего не понимаю — есть ReadByte и ReadAsync. Где ReadByteAsync?
З.Ы.Ы. У них там ещё маленько legacy есть, вроде BeginRead. Т.е. концепцию "generic view of a sequence of bytes" не осилить в первой итерации.
Если не поможет, будем действовать током... 600 Вольт (C)
Re[3]: Об очередном антипаттерне. Модель акторов.
От: Mamut Швеция http://dmitriid.com
Дата: 25.08.15 06:21
Оценка:
M>>В том же Erlang'е практически все описанные «проблемы» давно, по сути, решены и описываются во первых же строках любой книги по Erlang'у. Курить те же деревья супервизоров.

LP>Ну, начнем с того, что у меня не erlang, а jvm или c++. И как минимум там это действительно выглядит как антипаттерн.


Поэтому и первая часть моего сообщения Без поддержки среды это все быстро становится очень и очень печальным. Потому что, скажем «по процессу/потоку на пользователя» в Erlang'е рассматривается обычно на уровне туториалов, и проблем не вызывает

LP> Про erlang ничего сказать не могу, не читал, не использовал, не сталкивался. Но с эрлангом или без, от конечного автомата все равно не убежите. Другое дело, он может быть замаскирован корутинами или продожениями. Но в любом случае будет интересно увидеть, что же так сказать эрланг животворящий делает. Как будет выглядеть на эрланге приведенный мной пример (с Response1 и Response2)?


В простейшем случае используется поставляемый с Erlang'ом gen_server (по сути, определение интерфейса). Код, реализующий gen_server, должен реализовать, по сути, следующее (псевдокод):


//внешний API

message1(Data):
  return gen_server.call({message_pattern_1, Data})

message2(Data):
  return gen_server.call({message_pattern_2, Data})

message3(Data):
  return gen_server.call({message_pattern_3, Data})

//реализация gen_server'а
init():
  return gen_server.init(InitialState)

handle_call({message_pattern_1, Data}, CurrentState):
   обрабатываем message 1
   return {{response1, Data}, NewCurrentState}
handle_call(message_pattern_2, CurrentState):
   обрабатываем message 2
   return {response2, NewCurrentState}
handle_call({message_pattern_3, Data}, CurrentState):
   обрабатываем message 3
   return {response2, NewCurrentState}


Вызывающий код:


Handle = some_module.init()

Response1 = some_module.message1(Handle, Data1)
Response2 = some_module.message2(Handle, Data2)
Response3 = some_module.message3(Handle, Data3)


Никаких AWAIT_RESPONSE, потому что это все уже реализовано внутри стандартного gen_server'а
— handle_call — реализация синхронного вызова
— handle_cast — реализация асинхронного вызова, обычно по принципу "Fire and forget"
В любом случае: init — это создание нового процесса/потока, в который отсылаются сообщения


dmitriid.comGitHubLinkedIn
Re[8]: Корутины в C#
От: Sinix  
Дата: 25.08.15 08:18
Оценка:
Здравствуйте, -MyXa-, Вы писали:


MX>Какие были проблемы использовать ISequentialStream в C#, что понадобилось сделать монструозный (десять страниц одних оглавлений... ) System.IO.Stream?


Кэп: потому что Stream — это аналог IStream.
Кэп #2: таймауты, тек. позиция, seek, асинхронное чтение, тип потока (чтение/запись/оба), flush etc. Если этого нет из коробки, то на ровном месте придётся городить тонну костылей. Для каждого из мест использования.

И да, если для вас класс с парой десятков свойств-методов монструозный — вы точно разрабатываете под шарп в IDE? Если нет — не всё ли равно, что там у шарповодов?


MX>З.Ы. Я в C# ничего не понимаю — есть ReadByte и ReadAsync. Где ReadByteAsync?

А зачем? Хоть один сценарий для такого изврата есть?
Re[12]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 08:34
Оценка:
Здравствуйте, alex_public, Вы писали:

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


_>>>1. Это модель акторов или нет?

LP>>Нет

_>Почему? )


Потому что это callback. Я думал, это очевидно.
Callback отличается от актора тем, что он снабжен контекстом вызова. Response приходит в определенном контексте — в котором был послан request.
В случае актора reponse может прийти в ЛЮБОМ контексте. Он может прийти даже сам по себе, без всякого request, если другой актор послал это сообщение по какому-то событию,
хотя в данном случае Response не совсем правильное название для такого сообщения.
Поэтому нужен конечный автомат, чтобы разобрать состояния.

Callback:
if (state == 1)//В Callback я знаю, что state == 1, поэтому вызываю calc1
    call(request1, response -> {calc1(response)});
else if (state == 2)//В Callback я знаю, что state == 2, поэтому вызываю calc2
    call(request2, response -> {calc2(response)});


Actor:
if (state == 1) {
    fsmState = WAIT_FOR_RESPONSE1;
    call(request1);
}
else if (state == 2) {
    fsmState = WAIT_FOR_RESPONSE2;
    call(request2);
}

//Обработка
void messageReceived(Response response) {
    if (fsmState == WAIT_FOR_RESPONSE1)
        calc1(response);
    else if (fsmState == WAIT_FOR_RESPONSE2)
        calc2(response);
    else if (fsmState == NO_REQUEST)//здесь сообщение Response пришло без Request
        processEvent(response);
}


Актор можно переписать, сделав в какой-то степени похожим на колбак, то есть снадбив контекстом вызова, при помощи сопрограммы:

if (state == 1) {
    response = await call(request1);
    calc1(response);
}
else if (state == 2) {
    response = await call(request2);
    calc2(response);
}

//Обрабатываем самопроизвольный приход Response (хотя название Response для сообщения в данном случае не самое удачное)
void messageReceived(Response response) {
    processEvent(response);
}


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

_>Хм, а разве есть какое-то принципиальное отличие этого моего примера и данного кода

_>из пункта номер 1 изначального сообщения темки? ) Заменяем CalculateSomething на DownloadData, a someHardCalculation на "обработка следующих сообщений в очереди (GUI приложения)"...

Если бы ты взял не первый пример (который как раз демонстрировал НЕПРАВИЛЬНОЕ использование актора), а последний, ты бы не написал это сообщение.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[4]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 08:54
Оценка:
Здравствуйте, Mamut, Вы писали:

M>>>В том же Erlang'е практически все описанные «проблемы» давно, по сути, решены и описываются во первых же строках любой книги по Erlang'у. Курить те же деревья супервизоров.


LP>>Ну, начнем с того, что у меня не erlang, а jvm или c++. И как минимум там это действительно выглядит как антипаттерн.


M>Handle = some_module.init()


M>Response1 = some_module.message1(Handle, Data1)

M>Response2 = some_module.message2(Handle, Data2)
M>Response3 = some_module.message3(Handle, Data3)
M>[/code]

M>Никаких AWAIT_RESPONSE, потому что это все уже реализовано внутри стандартного gen_server'а

M>— handle_call — реализация синхронного вызова
M>— handle_cast — реализация асинхронного вызова, обычно по принципу "Fire and forget"
M>В любом случае: init — это создание нового процесса/потока, в который отсылаются сообщения

Узнаю, я сделал похожее в одном легасе акторе, чтобы уменьшить количество состояний.
Коротко — актор делал ряд запросов к другому актору, который присылал сообщение в ответ. Но это сообщение приходило не только в ответ на _разные_запросы, но еще и само по себе. Я сделал callback и снадбил каждую отправку сообщений уникальным идентификатором. Если ответ пришел в ответ на сообщение, посланное через callback, вызывался callback. Если без callback, вызывался обычный receive. Правда, в отличие от эрланга, у меня вызов был не синхронным и не блокирующим (callback). То, что я увидел в приведенном выше коде — это обычный блокирующий вызов. Даже не касаясь того, что делать блокирующий вызов в акторе сродни безумию (может мудрый эрланг это как-то обходит), задам другой вопрос — смысл тогда использовать актор, если во время ожидания запроса актор заблокирован и не может обработать другие сообщения?
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[5]: Об очередном антипаттерне. Модель акторов.
От: Mamut Швеция http://dmitriid.com
Дата: 25.08.15 09:47
Оценка:
LP>Даже не касаясь того, что делать блокирующий вызов в акторе сродни безумию (может мудрый эрланг это как-то обходит), задам другой вопрос — смысл тогда использовать актор, если во время ожидания запроса актор заблокирован и не может обработать другие сообщения?

Тогда можно делать не call (блокирующий вызов), а cast (асинхронный вызов).

Если мы ожидаем ответа от асинхронного вызова, то нам нужно ожидать получение этого ответа. Для этого в Эрланге есть прекрасная конструкция receive. Да, это примерно соответсвует wait_for_что_то_там из приведенного тобой примера.


some_function() ->
   async1(),
   asyn2(),
   asyn3(),

   wait_for_response([]).  %% если мы не хотим блокировать
                           %% выполнение, и эту функцию тоже
                           %% можно вынести в отдельный процесс/поток

wait_for_response(ResponseAccum) when length(ResponseAccum) == 3->
  ResponseAccum; %% возвращаем аккумулированные ответы
wait_for_response(ResponseAccum) ->
 %% при получении ответа просто добавляем ответ в список ответов
 %% и продолжаем ждать. tail call optmization
 %% позволяет делать рекурсивный вызов сколько угодно раз

 %% receive выбирает из сообщений, поступающих в процесс,
 %% те, что соответсвуют паттерну. Ожидание не стоит ничего.
 %% Вплоть до того, что процесс могут просто выключить из очереди
 %% на обработку до тех пор, пока к нему не придет сообщение
 receive
   {response1, Data} -> wait_for_response(ResponseAccum ++ Data)
   {response2, Data} -> wait_for_response(ResponseAccum ++ Data)
   {response3, Data} -> wait_for_response(ResponseAccum ++ Data)
 %% можно опционально добавить таймаут, и не один, если надо
 after
    1000 -> log("все ждем ответа");
    10000 -> 
       log("ответа не дождались, аборт"),
       error("Aborting")
 end.


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

Плюс сами процессы стоят копейки (зеленые потоки), стоимость их порождения можно увидеть может быть на каких-то сверхнагруженных системах. И то... Весь boilerplate по их управлению (даже выписаные мной receive ... end) обычно давно упаковаан в стандартные библиотеки, решающие практические проблемы: (gen — generic) gen_server, gen_supervisor, gen_fsm (да, даже машина состояний, если вдруг надо будет ).

Поэтому решение задач выглядит обычно как «ага, нам нужно пяток исполнителей, собранных в одну группу, к ним будет обращаться вот эта гроздь клиентов, которая динамически изменяется, их lifecycle будет отслеживать (автоматически, замечу) вот этот контролирующий процесс». Все это нанизывается друг на друга, и программирование с их использованием редко отличается от программирования в стиле
X = f(),
Y = g(),
Z = h(X, Y).


несмотря на то, что на фоне — полтора миллиона процессов и маленькая тележка


dmitriid.comGitHubLinkedIn
Re[3]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 09:51
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>Ну, начнем с того, что у меня не erlang, а jvm или c++. И как минимум там это действительно выглядит как антипаттерн. Про erlang ничего сказать не могу, не читал, не использовал, не сталкивался. Но с эрлангом или без, от конечного автомата все равно не убежите. Другое дело, он может быть замаскирован корутинами или продожениями.


а причём тут конечные автоматы? если ты про реализацию, то конечные автоматы нужны только для stackless coroutines. в осталльных случаях просто переходит переключение стёков, зелёные потоки в эрланге отличаются от stackful coroiutines в C только тем, что VM обеспечивает автоматическое переключение потоков с какой-то периодичностью, например в процессе выделения памяти
Люди, я люблю вас! Будьте бдительны!!!
Re[2]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 09:53
Оценка:
Здравствуйте, Mamut, Вы писали:

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


из твоих слов получается что акторы являются антипаттерном в любом языке кроме эрланга
Люди, я люблю вас! Будьте бдительны!!!
Re[4]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 10:04
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

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


LP>>Ну, начнем с того, что у меня не erlang, а jvm или c++. И как минимум там это действительно выглядит как антипаттерн. Про erlang ничего сказать не могу, не читал, не использовал, не сталкивался. Но с эрлангом или без, от конечного автомата все равно не убежите. Другое дело, он может быть замаскирован корутинами или продожениями.


BZ>а причём тут конечные автоматы?


Если нет coroutines, то нужно либо писать автомат, либо делать синхронный вызов с блокировкой, либо делать хитрый callback как описано здесь: http://rsdn.ru/forum/philosophy/6157243.1
Автор: LaPerouse
Дата: 25.08.15


BZ>если ты про реализацию, то конечные автоматы нужны только для stackless coroutines. в осталльных случаях просто переходит переключение стёков, зелёные потоки в эрланге отличаются от stackful coroiutines в C только тем, что VM обеспечивает автоматическое переключение потоков с какой-то периодичностью, например в процессе выделения памяти


Это-то понятно. Значит, все таки coroutines. Что и требовалось доказать.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[6]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 10:18
Оценка:
Здравствуйте, Mamut, Вы писали:


LP>>Даже не касаясь того, что делать блокирующий вызов в акторе сродни безумию (может мудрый эрланг это как-то обходит), задам другой вопрос — смысл тогда использовать актор, если во время ожидания запроса актор заблокирован и не может обработать другие сообщения?


M>Тогда можно делать не call (блокирующий вызов), а cast (асинхронный вызов).


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

M>Если мы ожидаем ответа от асинхронного вызова, то нам нужно ожидать получение этого ответа. Для этого в Эрланге есть прекрасная конструкция receive. Да, это примерно соответсвует wait_for_что_то_там из приведенного тобой примера.


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

resp = await cast(actor, msg);//происходит возврат управления из функции, актор готов принимать сообщения

//Отсюда выполнение продолжится, когда придет ответ на запрос
process(resp);


Таким образом все может быть сведено к этому:

M>Все это нанизывается друг на друга, и программирование с их использованием редко отличается от программирования в стиле

M>
M>X = f(),
M>Y = g(),
M>Z = h(X, Y).
M>
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[5]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 10:23
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>>>Ну, начнем с того, что у меня не erlang, а jvm или c++. И как минимум там это действительно выглядит как антипаттерн. Про erlang ничего сказать не могу, не читал, не использовал, не сталкивался. Но с эрлангом или без, от конечного автомата все равно не убежите. Другое дело, он может быть замаскирован корутинами или продожениями.


BZ>>а причём тут конечные автоматы?


LP>Если нет coroutines, то нужно либо писать автомат,


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

LP>Это-то понятно. Значит, все таки coroutines. Что и требовалось доказать.


не coroutines, а green threads
Люди, я люблю вас! Будьте бдительны!!!
Re[3]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 10:30
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

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


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


BZ>из твоих слов получается что акторы являются антипаттерном в любом языке кроме эрланга


Если есть хотя бы yield return null, то писать их становится сильно проще. Если их нет (java), то просто беда.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[6]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 10:34
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

BZ>вот тут у тебя лог. ошибка. из того, что в отсутствии короутин нужно делать автомат — не следует что все короутины реализуются только через автоматы


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

LP>>Это-то понятно. Значит, все таки coroutines. Что и требовалось доказать.

BZ>не coroutines, а green threads

Как без корутин сделать такой код

resp = await cast(actor, msg);//происходит возврат управления из функции, актор готов принимать сообщения

//Отсюда выполнение продолжится, когда придет ответ на запрос
process(resp);
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[4]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 10:35
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>Если есть хотя бы yield return null, то писать их становится сильно проще. Если их нет (java), то просто беда.


да я вобщето чисто мамута троллю. есть у него такие фанатичные заскоки...
Люди, я люблю вас! Будьте бдительны!!!
Re[7]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 10:37
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>Ты неправильно прочитал. Я нигде не писал, что для корутин нужно писать конечный автомат (хотя для безстековых нужно, но это особенность реализации). Но в отсутствии корутин нужно писать конечный автомат.


это твои слова или нет: "Но с эрлангом или без, от конечного автомата все равно не убежите. Другое дело, он может быть замаскирован корутинами или продожениями." ?
Люди, я люблю вас! Будьте бдительны!!!
Re[8]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 10:45
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

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


LP>>Ты неправильно прочитал. Я нигде не писал, что для корутин нужно писать конечный автомат (хотя для безстековых нужно, но это особенность реализации). Но в отсутствии корутин нужно писать конечный автомат.


BZ>это твои слова или нет: "Но с эрлангом или без, от конечного автомата все равно не убежите. Другое дело, он может быть замаскирован корутинами или продожениями." ?


Ну стековые корутины это вообще экзотика. При слове корутины все представляют себе yeild return иил async/await. Так что следовало читать это сообщение так:
"Но с эрлангом или без, от конечного автомата все равно не убежите. Другое дело, он может быть замаскирован безстековыми корутинами или продожениями." ?
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[3]: Об очередном антипаттерне. Модель акторов.
От: Mamut Швеция http://dmitriid.com
Дата: 25.08.15 10:52
Оценка:
M>>Практически все описаные антипаттерны возникают из отсутсвия в языке и среде нативной поддержки собственно модели акторов.

BZ>из твоих слов получается что акторы являются антипаттерном в любом языке кроме эрланга


Из моих слов получается:

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


И это — так


dmitriid.comGitHubLinkedIn
Re[7]: Об очередном антипаттерне. Модель акторов.
От: Mamut Швеция http://dmitriid.com
Дата: 25.08.15 10:55
Оценка:
LP>Это-то понятно. Но пример в исходном сообщении как раз показывает, что обработка ответа на асинхронный вызов может быть сложной, так как в нетривиальном случае обработка зависит от состояния.

Обработка любого ответа в любом случае может быть нетривиальной

LP>
LP>resp = await cast(actor, msg);//происходит возврат управления из функции, актор готов принимать сообщения

LP>//Отсюда выполнение продолжится, когда придет ответ на запрос
LP>process(resp);
LP>


Да, promises и прочая немного помогают. На практике для них все равно чаще всего нет внятной инфраструктуры по управлению ими (возможно, еще появится с ростом популярности)


dmitriid.comGitHubLinkedIn
Re[9]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 11:02
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>"Но с эрлангом или без, от конечного автомата все равно не убежите. Другое дело, он может быть замаскирован безстековыми корутинами или продожениями." ?


нет в эрланге ни того, ни жругого, ни третьего. там зелёные потоки

LP>Ну стековые корутины это вообще экзотика. При слове корутины все представляют себе yeild return иил async/await.


вот с этого следовало начинать

идея сопрограмм появилась в 60-х годах, в частности в Симуле-67, и до недавнего времени была представлена исключительно стёковыми сопрограммами. их несложно реализовать на уровне ассемблера, и даже в C есть набор функций, достаточный для их реализации — alloca/setjmp/longjmp

а генерация конечных автомтов — это как рах экзотика, реализованная только в C#. я лично о ней впервые услышал несколько месяцев назад, когда стал изучать пропозалы C++
Люди, я люблю вас! Будьте бдительны!!!
Re[8]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 11:16
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

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


LP>>Как без корутин сделать такой код


BZ>3. green threads — это stackful coroutines


То есть coroutines. Чтд.

BZ>с регулярным автоматическим переключением между ними, реализованным в VM. ruby/erlang делают это через определённое кол-во шагов интерпретации, ghc — при выделении очередного блока памяти (а память в single-assignment языках выделяется постоянно)


Тут нужно переключать не абы когда (как в случае c green threads в общем случае), а именно после отправки асинхронного сообщения, и возвращать управление после получения ответа на запрос.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[8]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 11:23
Оценка:
Здравствуйте, Mamut, Вы писали:


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


M>Обработка любого ответа в любом случае может быть нетривиальной


Ну в примере из исходного сообщения как раз показан простой и сложный способ обработки ответа.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[9]: Об очередном антипаттерне. Модель акторов.
От: Mamut Швеция http://dmitriid.com
Дата: 25.08.15 11:26
Оценка:
LP>Ну в примере из исходного сообщения как раз показан простой и сложный способ обработки ответа.

Я, если честно, не вижу там простого-сложного, и в чем вообще проблема


dmitriid.comGitHubLinkedIn
Re[10]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 11:29
Оценка:
Здравствуйте, Mamut, Вы писали:


LP>>Ну в примере из исходного сообщения как раз показан простой и сложный способ обработки ответа.


M>Я, если честно, не вижу там простого-сложного, и в чем вообще проблема


То есть для тебя нет разницы между этим:

ProcessingResult process(data1, data2) {
      future1 = performer1.request(new Request1(data1));
      future2 = performer2.request(new Request2(data2));
      return process(future1.get(), future2.get());
}

ProcessingResult2 processAnother(data) {
      return performer1.request(new Request1(data));
}


и этим

activateState1();
actor1.sendMessage(new Request1(data1));
actor2.sendMessage(new Request2(data2));
state = STATE1_WAIT_FOR_RESPONSE1_RESPONSE2;



void response1Handler(Response1 resp) {
     this.resp1 = resp;
     if (state == STATE1_WAIT_FOR_RESPONSE1_RESPONSE2) {
         state = STATE1_WAIT_FOR_RESPONSE2;
     } else if (state == STATE1_WAIT_FOR_RESPONSE1){
       process(this.resp1, this.resp2);
       someCommonForState1State2Processing();
       state = STATE1_PROCESSED;
     } else if (state == STATE2_WAIT_FOR_RESPONSE1) {
       //Здесь другой контекст (STATE2) и совершенно другое вычисление
       doAnotherProcessing(this.resp1);
       someCommonForState1State2Processing();
       state = STATE2_PROCESSED;
     } else if (...){}//Обработка других комбинаций
}

void response2Handler(Response2 resp) {
     this.resp2 = resp;
     if (state == STATE1_WAIT_FOR_RESPONSE1_RESPONSE2) {
         state = STATE1_WAIT_FOR_RESPONSE1;
     } else if (state == STATE1_WAIT_RESPONSE2) {
       process(this.resp1, this.resp2);
       someCommonForState1State2Processing();
       state = STATE1_PROCESSED;
     }
}
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[13]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 25.08.15 11:33
Оценка:
Здравствуйте, LaPerouse, Вы писали:

_>>Почему? )

LP>Потому что это callback. Я думал, это очевидно.

Что ещё за callback через очередь сообщений? ) Ну да ладно, пускай будет для простоты обсуждения. )))

LP>Callback отличается от актора тем, что он снабжен контекстом вызова. Response приходит в определенном контексте — в котором был послан request.

LP>В случае актора reponse может прийти в ЛЮБОМ контексте. Он может прийти даже сам по себе, без всякого request, если другой актор послал это сообщение по какому-то событию,

А можно увидеть определение актора, которое обязывает нас принимать произвольное число непонятных сообщений? ) С чего вообще актор обязан принимать какие-то сообщения? Если скажем ему для работы не нужны никакие дополнительных данные...

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

LP>Поэтому нужен конечный автомат, чтобы разобрать состояния.

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

LP>Callback:

LP>...
LP>Actor:
LP>...

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

LP>Актор можно переписать, сделав в какой-то степени похожим на колбак, то есть снадбив контекстом вызова, при помощи сопрограммы:

LP>..

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

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


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

_>>Хм, а разве есть какое-то принципиальное отличие этого моего примера и данного кода

_>>из пункта номер 1 изначального сообщения темки? ) Заменяем CalculateSomething на DownloadData, a someHardCalculation на "обработка следующих сообщений в очереди (GUI приложения)"...
LP>Если бы ты взял не первый пример (который как раз демонстрировал НЕПРАВИЛЬНОЕ использование актора), а последний, ты бы не написал это сообщение.

Так а почему оно не правильное, если ты сам согласился, что получился удобный код? )
Re[11]: Об очередном антипаттерне. Модель акторов.
От: Mamut Швеция http://dmitriid.com
Дата: 25.08.15 11:35
Оценка:
M>>Я, если честно, не вижу там простого-сложного, и в чем вообще проблема

LP>То есть для тебя нет разницы между этим:


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


dmitriid.comGitHubLinkedIn
Re[14]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 11:48
Оценка:
Здравствуйте, alex_public, Вы писали:

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


_>>>Почему? )

LP>>Потому что это callback. Я думал, это очевидно.

_>Что ещё за callback через очередь сообщений? ) Ну да ладно, пускай будет для простоты обсуждения. )))


Очередь — это особенность реализации. К самой концепции callback-ов не имеющая отношения.

In computer programming, a callback is a piece of executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at some convenient time.


LP>>Callback отличается от актора тем, что он снабжен контекстом вызова. Response приходит в определенном контексте — в котором был послан request.

LP>>В случае актора reponse может прийти в ЛЮБОМ контексте. Он может прийти даже сам по себе, без всякого request, если другой актор послал это сообщение по какому-то событию,

_>А можно увидеть определение актора, которое обязывает нас принимать произвольное число непонятных сообщений? ) С чего вообще актор обязан принимать какие-то сообщения? Если скажем ему для работы не нужны никакие дополнительных данные...


Ну да, в hellow world они действительно красивые и причесанные. Только вот в реальной практике почему-то 90 процентов акторов выглядят именно так, как я показал.

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

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

LP>>Поэтому нужен конечный автомат, чтобы разобрать состояния.

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


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

LP>>Callback:

LP>>...
LP>>Actor:
LP>>...

_>Вот прямо в данном примере видно, что зачем-то объединили в один актор три независимых дела. Если их разделить на три отдельных актора, то никаких проблем уже не возникает.


Где объединил-то? Используются как раз три разных актора. ))

_>Сопрограммы используются для линеаризации асинхронного кода. Не важно какого происхождение. На базе системных потооков или лёгких потоков или вообще из асинхронного IO. По твому получается, что любой нелинеризованный асинхронный код обязательно содержит конечный автомат. Это весьма забавное утверждение. )))


Ну, это ты хорошо за меня придумал. Это где из моих слов выходит такое?

_>>>Хм, а разве есть какое-то принципиальное отличие этого моего примера и данного кода

_>>>из пункта номер 1 изначального сообщения темки? ) Заменяем CalculateSomething на DownloadData, a someHardCalculation на "обработка следующих сообщений в очереди (GUI приложения)"...
LP>>Если бы ты взял не первый пример (который как раз демонстрировал НЕПРАВИЛЬНОЕ использование актора), а последний, ты бы не написал это сообщение.
_>Так а почему оно не правильное, если ты сам согласился, что получился удобный код? )

Код получился удобным не в акторе. Эдак можно каждый асинхронный обработчик называть актором.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[12]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 11:52
Оценка:
Здравствуйте, Mamut, Вы писали:

M>>>Я, если честно, не вижу там простого-сложного, и в чем вообще проблема


LP>>То есть для тебя нет разницы между этим:


M>Только в том, что код ужасен. Но это проистекает из убогости языка/библиотек. Это во-первых.


Так ты не показал, как удобно.

M>Во-вторых, первый код не эквивалентен второму.


Ну да, об этом написано в исходном сообщении. Но забавно, что в большинстве случаев они таки выходят эквивалентными )
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[13]: Об очередном антипаттерне. Модель акторов.
От: Mamut Швеция http://dmitriid.com
Дата: 25.08.15 11:55
Оценка:
M>>Только в том, что код ужасен. Но это проистекает из убогости языка/библиотек. Это во-первых.
LP>Так ты не показал, как удобно.

Я показал пример с gen_server и с использованием только примитива receive.

M>>Во-вторых, первый код не эквивалентен второму.

LP>Ну да, об этом написано в исходном сообщении. Но забавно, что в большинстве случаев они таки выходят эквивалентными )

Чтоа?


dmitriid.comGitHubLinkedIn
Re[11]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 12:05
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>Просто открываем любой C# проект — код будет усыпан yield return и async-ами. В С++ проектах редко можно встретить применение сопрограмм. Так что есть экзотика?


для человека, следующего ра развитием ЯП и знающего десятки языков начиная с фортрана и лиспа — stackless экзотика. для человека, знакомого только с C# — наоборот
Люди, я люблю вас! Будьте бдительны!!!
Re[13]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 12:13
Оценка:
Здравствуйте, LaPerouse, Вы писали:

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


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

так что множество языков — от С до эрланга эту проблему решают без языковой поддержки. твоя проблема в том что ты не знаешь ничего кроме своего C# и начинаешь рассуждать о других языках, думая что они должны быть устроены точно так же. а когда оказывается чсто это не так, сюбда добавляются рассуждения о том что все олстальные языки — экзотика и правильные сопрограммы у нас появились всего 5 лет назщад
Люди, я люблю вас! Будьте бдительны!!!
Re[12]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 12:15
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

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


LP>>Просто открываем любой C# проект — код будет усыпан yield return и async-ами. В С++ проектах редко можно встретить применение сопрограмм. Так что есть экзотика?


BZ>для человека, следующего ра развитием ЯП и знающего десятки языков начиная с фортрана и лиспа — stackless экзотика. для человека, знакомого только с C# — наоборот


Череп не жмет?
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[7]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 25.08.15 12:35
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>Как без корутин сделать такой код

LP>
LP>resp = await cast(actor, msg);//происходит возврат управления из функции, актор готов принимать сообщения
LP>//Отсюда выполнение продолжится, когда придет ответ на запрос
LP>process(resp);
LP>


Вот это как раз и есть классическая линеаризация асинхронного кода. Только вот она мягко говоря не всегда нужна (а я бы вообще предложил не пользоваться этим инструментом, только затрудняющим понимание кода (того что реально происходит под капотом, скажем большинство C# программистов даже близко не представляют себе что там стоит внутри за async/await)).

Начнём с того, что в очень многих случаях process может исполняться внутри самого асинхронного кода и соответственно никаких подобных проблем не возникает. Кстати это тоже вполне укладывается в модель акторов — молча отработал (не работая с общей памятью) и умер. Исключений, когда process нельзя вызывать в асинхронном коде, на самом деле не много. С ходу в голову приходят:

1. GUI (работа с ним из других потоков обычно запрещена). Однако в таком случае родительский код, исполняющий process — это как раз GUI поток и соответственно уже имеет встроенную (и интенсивно использующуюся, причём с помощью мощных библиотечных инструментов, реализующих не просто конечные автоматы, а сложную надстройку над ними с подписками и т.п., обычно на базе ООП) очередь сообщений. Соответственно здесь у нас по сути сама собой образуется неявная модель акторов (ну если конечно асинхронный код не будет работать с общей памятью). Это в точности мой пример. И сопрограммы тут, как видно, не обязательны.

2. Распараллеливание вычислений. Когда мы для ускорения хотим выполнить некий код (например цикл) сразу в нескольких потоках, а результаты соответственно собираем в родительском коде для дальнейшей обработки. Здесь естественно никакие модели акторов не подходят. Для таких целей есть готовые удобные инструменты типа openmp и т.п. бесчисленные библиотеки с реализацией parallel_for и т.п. Реализуется это всё внутри через банальную блокировку до тех пор, пока не будут готовы все данные из запущенных веток. Сопрограммы здесь тем более не нужны.

3. Использование асинхронного IO. В этом случае асинхронный код вообще нам не принадлежит. Но при этом нам доступны соответствующие callback'и (в этом случае самые классические), которые легко упаковываются в удобные структуры. Смотри например Boost.Asio. Опять же нет никакой обязательной потребности в сопрограммах.

Какие ещё будут примеры асинхронного кода, где крайне необходима линеаризация?)
Re[16]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 12:38
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

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


LP>>У балаболов всегда все легко и просто.


BZ>слушай, я не люблю всю эту машинерию с модераторами. когда я говорю о твоих скромных познаниях вне C# — я говорю о технических аспектах, я например точно так же не знаю C#. когда ты начинаешь разбрасываться обидными словами — это уже нехорошо


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

LP>>И виртуальную машину с сопрограммами они за денек сделают,


BZ>было дело, я пока был в отпуске, сообразил как сделать сопрограммы на setjmp (а мне их в C страшно не хватало!), потом приехал залез в справку по борланду и там в статье по setjmp написано — их можно использовать для сопрограмм. так что это вполне штатная фича была и библиотеку я позже таки сделал


Рад за тебя (серьезно, без шуток).
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[9]: Корутины в C#
От: -MyXa- Россия  
Дата: 25.08.15 12:50
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Кэп #2: таймауты, тек. позиция, seek, асинхронное чтение, тип потока (чтение/запись/оба), flush etc. Если этого нет из коробки, то на ровном месте придётся городить тонну костылей. Для каждого из мест использования.


В чём проблема реализовать асинхронное чтение в IStream::Read с помощью async/await?
Если не поможет, будем действовать током... 600 Вольт (C)
Re[15]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 25.08.15 12:50
Оценка:
Здравствуйте, LaPerouse, Вы писали:

_>>Что ещё за callback через очередь сообщений? ) Ну да ладно, пускай будет для простоты обсуждения. )))

LP>Очередь — это особенность реализации. К самой концепции callback-ов не имеющая отношения.
LP>

LP>In computer programming, a callback is a piece of executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at some convenient time.


И какой конкретно код передаётся для последующего вызова в моём примере? )

_>>А можно увидеть определение актора, которое обязывает нас принимать произвольное число непонятных сообщений? ) С чего вообще актор обязан принимать какие-то сообщения? Если скажем ему для работы не нужны никакие дополнительных данные...

LP>Ну да, в hellow world они действительно красивые и причесанные. Только вот в реальной практике почему-то 90 процентов акторов выглядят именно так, как я показал.

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

LP>Вообще, когда актору требуется получить что-то от другого актора для обработки сообщения — тривиальнейшая ситуация. Это известно любому, кто хоть немного сталкивался с акторами.


Естественно. Но это не является обязательным требованием на право называться актором.

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

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

LP>Настолько не нужны, что даже разработчики akka рекомендуют делать акторы через автоматы, поддержка которых сделана прямо в akka ))

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

_>>Сопрограммы используются для линеаризации асинхронного кода. Не важно какого происхождение. На базе системных потооков или лёгких потоков или вообще из асинхронного IO. По твому получается, что любой нелинеризованный асинхронный код обязательно содержит конечный автомат. Это весьма забавное утверждение. )))

LP>Ну, это ты хорошо за меня придумал. Это где из моих слов выходит такое?

Так ты же сам писал, что или сопрограммы или конечный автомат. )

_>>Так а почему оно не правильное, если ты сам согласился, что получился удобный код? )

LP>Код получился удобным не в акторе. Эдак можно каждый асинхронный обработчик называть актором.

Если это отдельно исполняющаяся сущность, не работающая с общей памятью, а передающая данные через сообщения, то почему бы и нет? )
Re[8]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 12:51
Оценка:
Здравствуйте, alex_public, Вы писали:

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


LP>>Как без корутин сделать такой код

LP>>
LP>>resp = await cast(actor, msg);//происходит возврат управления из функции, актор готов принимать сообщения
LP>>//Отсюда выполнение продолжится, когда придет ответ на запрос
LP>>process(resp);
LP>>


_>Вот это как раз и есть классическая линеаризация асинхронного кода. Только вот она мягко говоря не всегда нужна (а я бы вообще предложил не пользоваться этим инструментом, только затрудняющим понимание кода (того что реально происходит под капотом, скажем большинство C# программистов даже близко не представляют себе что там стоит внутри за async/await)).


А ты пробовал использовать async/await для реализации конечного автомата? Я пробовал и не раз (в яве, через библиотеку). Результат — кода стало в три раза меньше.

Почитай также здесь
http://docs.unity3d.com/ru/current/Manual/Coroutines.html

Сто процентов скриптов Юнити делаются при помощи "линеаризации асинхронного кода".
Сто процентов скриптов на Unreal Engine делаются при помощи "линеаризации асинхронного кода".

Мужики делают что-то не так?

_>Начнём с того, что в очень многих случаях process может исполняться внутри самого асинхронного кода и соответственно никаких подобных проблем не возникает. Кстати это тоже вполне укладывается в модель акторов — молча отработал (не работая с общей памятью) и умер. Исключений, когда process нельзя вызывать в асинхронном коде, на самом деле не много. С ходу в голову приходят:


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

Есть же пример, который я привел в корневом сообщении (последний)

1. Считаешь ты этот пример легким и читаемым по сравнению с синхронным случаем?
2. Считаешь ты этот пример легким и читаемым по сравнению с async/await?
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[10]: Корутины в C#
От: Sinix  
Дата: 25.08.15 13:24
Оценка:
Здравствуйте, -MyXa-, Вы писали:

MX>В чём проблема реализовать асинхронное чтение в IStream::Read с помощью async/await?

Проблема в том, что async\await не знает о внутренностях потока и о реальном API, которое используется для асинхронного чтения-записи (напомню, асинхронность достигается не запуском отдельного потока, а калбэками поверх IOCP).

Это api спрятано за теми самыми "легаси" BeginRead/Write. BeginXyzAsync — это просто сахар и в принципе без него спокойно можно обойтись. Как это делалось в четвёртом фреймворке, например.
Re[17]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 13:27
Оценка:
Здравствуйте, LaPerouse, Вы писали:

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


опять тебя отсутствие занний подводит — есть куча реализаций сопрограмм и зелёных потоков в различных инетпретаторах (ruby, python, js) и в виде внешних библиотек. кто ж виноват что ты ни о чём кроме c# hype не слышал??
Люди, я люблю вас! Будьте бдительны!!!
Re[11]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 13:37
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>Да нет, это ты приплел совершенно не в тему зеленые потоки и сейчас юлишь, пытаясь свести весь эрланг к ним.


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

LP>>>Тут нужно переключать не абы когда (как в случае c green threads в общем случае), а именно после отправки асинхронного сообщения, и возвращать управление после получения ответа на запрос.

BZ>>насколоько я понимаю, переключать нужно при ожидании ответа — если он ещё не готов. опять же советую тебе глядеть на green thread как разновдиность потоков вообще, просто более эффективно реализуемую.

LP>Чем это отличается это от того, что я написал?


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

LP>И с чего ты взял, что в эрланге все происходит именно так? Вон Мамут, который в отличие от тебя писал на эрланге, ничего подобного не приводит.


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

BZ>>а ты похоже всё пытаешься к своему миру C# свести, отсюда трудности


LP>К моему? Ну-ну. Я никогда не писал и ни планирую писать на С# и ссылаюсь на него лишь потому, что именно этот язык ввел понятия сопрограмм в мейнстрим и для многим именно мс-ская реализация является референсной.


ну перестань, а? в десятках языков это было, и организовано куда удобней чем stackless coroutines в C#, просто ты лично ни с чем иным не знаком. как мамут, честное слово
Люди, я люблю вас! Будьте бдительны!!!
Re[11]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 13:43
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>И с чего ты взял, что в эрланге все происходит именно так? Вон Мамут, который в отличие от тебя писал на эрланге, ничего подобного не приводит.


вероятно, всё дело в черепе
Люди, я люблю вас! Будьте бдительны!!!
Re[9]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 25.08.15 13:52
Оценка:
Здравствуйте, LaPerouse, Вы писали:

_>>Вот это как раз и есть классическая линеаризация асинхронного кода. Только вот она мягко говоря не всегда нужна (а я бы вообще предложил не пользоваться этим инструментом, только затрудняющим понимание кода (того что реально происходит под капотом, скажем большинство C# программистов даже близко не представляют себе что там стоит внутри за async/await)).

LP>А ты пробовал использовать async/await для реализации конечного автомата? Я пробовал и не раз (в яве, через библиотеку). Результат — кода стало в три раза меньше.

Сопрограммы для реализации конечного автомата? ) Это что-то новенькое... ))) Если мне надо реализовать конечный автомат (именно его, а не какое-то параллельное исполнение), то я уже показал с помощью какого инструмента я буду его реализовывать. И вряд ли у тебя получится удобнее. )

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

LP>Почитай также здесь

LP>http://docs.unity3d.com/ru/current/Manual/Coroutines.html

Кстати, в C# с async/await вообще надо настороже быть. Потому как описываемое в данной темке поведение (с исполнением продолжения в изначальном потоке) там наблюдается только при условие (при дефолтных настройках), что изначальный поток — это тот самый главный GUI поток. Если же запустить подобный код просто в каком-то потоке, то продолжение будет исполняться в произвольном свободном потоке из пула (это может даже оказаться тот же самый поток, где исполнялся асинхронный код, только после кучи никчемных переключений), а не в родительском потоке. Что сводит к нулю всю возможную пользу от сопрограмм.

Собственно из этого сомнительного решения сразу видно под что они затачивали своё решения — как раз под аналог моего примера с GUI.

LP>Сто процентов скриптов Юнити делаются при помощи "линеаризации асинхронного кода".

LP>Сто процентов скриптов на Unreal Engine делаются при помощи "линеаризации асинхронного кода".
LP>Мужики делают что-то не так?

Да, да, миллион мух не может ошибаться. )))

_>>Начнём с того, что в очень многих случаях process может исполняться внутри самого асинхронного кода и соответственно никаких подобных проблем не возникает. Кстати это тоже вполне укладывается в модель акторов — молча отработал (не работая с общей памятью) и умер. Исключений, когда process нельзя вызывать в асинхронном коде, на самом деле не много. С ходу в голову приходят:

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

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

LP>Есть же пример, который я привел в корневом сообщении (последний)

LP>1. Считаешь ты этот пример легким и читаемым по сравнению с синхронным случаем?
LP>2. Считаешь ты этот пример легким и читаемым по сравнению с async/await?

Данный пример реализуется как раз 2-ой случай из моего описание (распараллеливание). И очевидно не требует для своей реализации ни сопрограмм, ни акторов, ни конечных автоматом. Достаточно банальной блокировки (future.get), что ты и продемонстрировал.

Однако если захотеть реализовать данный пример с помощью акторов (т.е. по сути заменить передачу возвращаемого значения с future на message), то практически ничего не изменится. Если конечно не притаскивать зачем-то никчемные (тут) конечные автоматы.
Re[8]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 14:12
Оценка:
Здравствуйте, alex_public, Вы писали:

_>2. Распараллеливание вычислений. Когда мы для ускорения хотим выполнить некий код (например цикл) сразу в нескольких потоках, а результаты соответственно собираем в родительском коде для дальнейшей обработки. Здесь естественно никакие модели акторов не подходят. Для таких целей есть готовые удобные инструменты типа openmp и т.п. бесчисленные библиотеки с реализацией parallel_for и т.п. Реализуется это всё внутри через банальную блокировку до тех пор, пока не будут готовы все данные из запущенных веток. Сопрограммы здесь тем более не нужны.


как раз это далеко не всегда можно сделать на parallel_for. погляджи на TPL/TBB — там parallel_for предлагается для простых задач, а для более слодных есть граф выполнения, вполне в стиле акторов. вот тебе пример — архиватор:

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

соответственно реализовывается всё это графом сообщений, часть задач распараллеливается в пуле потоков, часть ограничена скоростью I/O и может работать через любые асинхронные средства
Люди, я люблю вас! Будьте бдительны!!!
Re[10]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 14:16
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Сопрограммы для реализации конечного автомата? ) Это что-то новенькое... ))) Если мне надо реализовать конечный автомат (именно его, а не какое-то параллельное исполнение), то я уже показал с помощью какого инструмента я буду его реализовывать. И вряд ли у тебя получится удобнее. )


когда в этот конечный автомат входит текущая позиция в стёке вызовов, вряд ли получится удобней чем с сопрограммами. преимущество сопрограмм — в том что код формально линейный, запросили данные — ту же получили ответ. не знаю какой ты инструмент имеешь в виду, но удобней resp = await ask() вряд ли будет
Люди, я люблю вас! Будьте бдительны!!!
Re[10]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 14:33
Оценка:
Здравствуйте, alex_public, Вы писали:

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


_>>>Вот это как раз и есть классическая линеаризация асинхронного кода. Только вот она мягко говоря не всегда нужна (а я бы вообще предложил не пользоваться этим инструментом, только затрудняющим понимание кода (того что реально происходит под капотом, скажем большинство C# программистов даже близко не представляют себе что там стоит внутри за async/await)).

LP>>А ты пробовал использовать async/await для реализации конечного автомата? Я пробовал и не раз (в яве, через библиотеку). Результат — кода стало в три раза меньше.

_>Сопрограммы для реализации конечного автомата? ) Это что-то новенькое... ))) Если мне надо реализовать конечный автомат (именно его, а не какое-то параллельное исполнение), то я уже показал с помощью какого инструмента я буду его реализовывать. И вряд ли у тебя получится удобнее. )


Мда... Собственно, на это можно прекращать дискуссию, поскольку ты вообще не представляешь себе предмет обсуждения.

Ключевые тезисы: иерархический конечный автомат, уменьшение количества состояний автомата за счет автоматического запоминания текущей позиции в стеке
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[11]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 14:38
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>Ключевые тезисы: иерархический конечный автомат, уменьшение количества состояний автомата за счет автоматического запоминания текущей позиции в стеке


вау! а почему бы не называть это просто сопрограммами, благо что этот термин применятся аж с 60-х?
Люди, я люблю вас! Будьте бдительны!!!
Re[12]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 14:43
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

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


LP>>Ключевые тезисы: иерархический конечный автомат, уменьшение количества состояний автомата за счет автоматического запоминания текущей позиции в стеке


BZ>вау! а почему бы не называть это просто сопрограммами, благо что этот термин применятся аж с 60-х?


Потому что нужно объяснить человеку, как сопрограммы помогают в реализации конечного автомата за счет уменьшения количества состояний. Которое достигается путем запоминания текущей позиции в стеке.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[9]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 25.08.15 14:50
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

BZ>как раз это далеко не всегда можно сделать на parallel_for. погляджи на TPL/TBB — там parallel_for предлагается для простых задач, а для более слодных есть граф выполнения, вполне в стиле акторов. вот тебе пример — архиватор:


parallel_for — это был всего лишь пример. В тот же openmp или tbb входит ещё много всего на эту тему.

BZ>первый поток обходит каталоги читает входные файлы

BZ>второй поток разбивает эти данные на сжимаемые куски
BZ>пул потоков выполняют задания на сжатие
BZ>потоки из того же пула выполняют задания на шифрование
BZ>послежний поток пишет готовые блоки в архив
BZ>соответственно реализовывается всё это графом сообщений, часть задач распараллеливается в пуле потоков, часть ограничена скоростью I/O и может работать через любые асинхронные средства

Да, это как раз пример неплохо реализуемый с помощью модели акторов. Однако я думаю ты не сомневаешься, что он там же легко реализуется и без неё с помощью того же пула потоков. Достаточно только немного изменить схему.
Re[14]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 15:02
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

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


LP>>>>Ключевые тезисы: иерархический конечный автомат, уменьшение количества состояний автомата за счет автоматического запоминания текущей позиции в стеке


BZ>>>вау! а почему бы не называть это просто сопрограммами, благо что этот термин применятся аж с 60-х?


LP>>Потому что нужно объяснить человеку, как сопрограммы помогают в реализации конечного автомата за счет уменьшения количества состояний. Которое достигается путем запоминания текущей позиции в стеке.


BZ>так он говорит "Если мне надо реализовать конечный автомат...". а ты в ответ ему говоришь о том как реализовывать "иерархический конечный автомат" — термин который ты сам только что придумал.


Никогда не слышал про иерархические конечные автоматы? А все туда же, лишь бы шашкой махать

http://www.cis.upenn.edu/~lee/06cse480/lec-HSM.pdf
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[11]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 25.08.15 15:04
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

_>>Сопрограммы для реализации конечного автомата? ) Это что-то новенькое... ))) Если мне надо реализовать конечный автомат (именно его, а не какое-то параллельное исполнение), то я уже показал с помощью какого инструмента я буду его реализовывать. И вряд ли у тебя получится удобнее. )

BZ>когда в этот конечный автомат входит текущая позиция в стёке вызовов, вряд ли получится удобней чем с сопрограммами. преимущество сопрограмм — в том что код формально линейный, запросили данные — ту же получили ответ. не знаю какой ты инструмент имеешь в виду, но удобней resp = await ask() вряд ли будет

Ты опять же говоришь про конечный автомат написанный ради обработки кривого распараллеливания. А не ради самой предметной задачи, где конечный автомат будет и даже в полностью однопоточном случае, скажем для реализации некого протокола, формата и т.п... И для этих целей я соответственно возьму данный http://www.boost.org/doc/libs/1_59_0/libs/msm/doc/HTML/ch03s04.html#d0e1462 инструмент. Ну а что касается реализации многопоточности, то я стараюсь её писать так, чтобы там конечные автоматы (не предметные) не возникали вовсе.

Ну и да, код удобнее resp = await ask() очевидно есть. Это resp = ask().
Re[12]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 15:31
Оценка:
Здравствуйте, alex_public, Вы писали:

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


LP>>Мда... Собственно, на это можно прекращать дискуссию, поскольку ты вообще не представляешь себе предмет обсуждения.

LP>>Ключевые тезисы: иерархический конечный автомат, уменьшение количества состояний автомата за счет автоматического запоминания текущей позиции в стеке

_>Конечно не представляю. ))) Я же не расставляю конечные автоматы по всему коду и по любому поводу.


Я тебе верю. Ты похоже вообще слабо представляешь, что такое конечный автомат.

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


Давай, жду код.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[12]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 15:36
Оценка:
Здравствуйте, Mamut, Вы писали:


LP>>Чем это отличается это от того, что я написал? И с чего ты взял, что в эрланге все происходит именно так? Вон Мамут, который в отличие от тебя писал на эрланге, ничего подобного не приводит.


M>Взял он с того, что он, в отличие от тебя, знает, о чем говорит. И что я не приводил? Из двух строчек моего кода ты сделал далеко идущие выводы о том, что где когда и как переключается?


Понимаешь, Булат буквально в первом или втором посту ответил на простой вопрос про coroutines в эрланге. То, что я не смог вытянуть у тебя за два дня общения. Значит, либо Булат фантазер (как я подумал сначала и похоже ошибся), либо уровень владения тобой предметом (эрланг) оставляет желать лучшего.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[10]: Об очередном антипаттерне. Модель акторов.
От: Sinix  
Дата: 25.08.15 16:24
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Кстати, в C# с async/await вообще надо настороже быть. Потому как описываемое в данной темке поведение (с исполнением продолжения в изначальном потоке) там наблюдается только при условие (при дефолтных настройках), что изначальный поток — это тот самый главный GUI поток.


Вот тут поправлю. Используется контекст синхронизации текущего потока (контекст по умолчанию запускает код ч/з пул потоков, это да). Любой из фреймворков (wf, wf, winforms, asp.net etc) может подсунуть свою синхронизацию sync context. Код может быть запущен в родительском потоке, в общем пуле, в отдельном потоке или вообще на другой ноде (как в orleans), всё зависит от реализации.


2all

Разумеется, это не значит, что на голый await стоит натягивать акторы. Тут уже писали выше кучу раз про "любая достаточно сложная распределённая программа содержит заново написанную, неспецифицированную, глючную и медленную реализацию половины языка Erlang". Так вот, await сам по себе — это не та половина Нужно что-то похожее — вэлкам в эрланг/скалу/orleans со всеми их плюсами и минусами. Не хочется — вам оно точно нужно?
Re[12]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 16:33
Оценка:
Здравствуйте, alex_public, Вы писали:

_>>>Сопрограммы для реализации конечного автомата? ) Это что-то новенькое... ))) Если мне надо реализовать конечный автомат (именно его, а не какое-то параллельное исполнение), то я уже показал с помощью какого инструмента я буду его реализовывать. И вряд ли у тебя получится удобнее. )


_>Ты опять же говоришь про конечный автомат написанный ради обработки кривого распараллеливания. А не ради самой предметной задачи, где конечный автомат будет и даже в полностью однопоточном случае, скажем для реализации некого протокола, формата и т.п... И для этих целей я соответственно возьму данный http://www.boost.org/doc/libs/1_59_0/libs/msm/doc/HTML/ch03s04.html#d0e1462 инструмент. Ну а что касается реализации многопоточности, то я стараюсь её писать так, чтобы там конечные автоматы (не предметные) не возникали вовсе.


ну к примеру классическая задача на inversion of control — когда данные читаются блоками по 80 байт, а выдаваться должны по 60 байт (приводилась ещё в 60-х как пример удобства сопрограмм). думаю, здесь ничего удобней них и не придумаешь

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

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


_>Ну и да, код удобнее resp = await ask() очевидно есть. Это resp = ask().


ты просто переносишь проблему внутрь ask(). а как она будет реализована? через описание конечного автомата в виде массива переходов состояний? так await куда проще
Люди, я люблю вас! Будьте бдительны!!!
Re[11]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 16:56
Оценка:
Здравствуйте, Sinix, Вы писали:

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


S>Разумеется, это не значит, что на голый await стоит натягивать акторы.


В Unity3d натянули на yield return null. Правда, не акторы, а автоматный код скриптов.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[12]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 17:22
Оценка:
Здравствуйте, LaPerouse, Вы писали:

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


вот видишь, и на яве сопрограммы есть, в виде чьих-то левых библиотек. с чего тогда у тебя вознили сомнения, что даже крутейшие корпорации не смогут их реализовать, неясно
Люди, я люблю вас! Будьте бдительны!!!
Re[13]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 25.08.15 17:43
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

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


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


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


Одно дело какая-то библиотека, которой пользуются полтора человека включая автора, другое дело добавлять что-то серьезное в jre. Какие сопрограммы, в яве даже лямбды появились буквально в прошлом году.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[13]: Об очередном антипаттерне. Модель акторов.
От: Mamut Швеция http://dmitriid.com
Дата: 25.08.15 19:13
Оценка:
LP>Понимаешь, Булат буквально в первом или втором посту ответил на простой вопрос про coroutines в эрланге. То, что я не смог вытянуть у тебя за два дня общения. Значит, либо Булат фантазер (как я подумал сначала и похоже ошибся), либо уровень владения тобой предметом (эрланг) оставляет желать лучшего.

Ты где-то спрашивал про то, как потоки реализованы в Эрланге? Нет. Ты спрашивал про то, как задача в Эрланге решается. Как она решается, я показал. Из этого ты нафантазировал себе какие-то далеко идущие выводы.

Пока что твой уровень общения указывает только на твое хамство, и ничего больше.


dmitriid.comGitHubLinkedIn
Re[12]: Об очередном антипаттерне. Модель акторов.
От: neFormal Россия  
Дата: 25.08.15 19:35
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>Как можно видеть конечный автомат при помощи сопрограмм реализован без введения трех явных состояний.


скорее над этим находятся другие состояния поведения.
а промежуточные состояния атаки часто и не нужны.
...coding for chaos...
Re[13]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 25.08.15 21:57
Оценка:
Здравствуйте, LaPerouse, Вы писали:

_>>Конечно не представляю. ))) Я же не расставляю конечные автоматы по всему коду и по любому поводу.

LP>Я тебе верю. Ты похоже вообще слабо представляешь, что такое конечный автомат.

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

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

LP>Давай, жду код.

Вся указанная логика легко кодируется в несколько строк:
BOOST_MSM_EUML_TRANSITION_TABLE(( 
    State1 + Response1 [state_(data1)=event(data1),!!state_(data2)] / (process, someCommonForState1State2Processing) == State1_Processed,
    State1 + Response2 [state_(data2)=event(data2),!!state_(data1)] / (process, someCommonForState1State2Processing) == State1_Processed,
    State2 + Response1 / (doAnotherProcessing, someCommonForState1State2Processing) == State2_Processed
),transition_table)

Но только при условие, что State1, State1_Processed, State2, State2_Processed — это состояния полученные из предметной области. А не очередные последствия кривой многопоточности — тогда и от них надо избавляться.

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

Если же мы попробуем написать на акторах аналог предложенного кода на future (т.е. без всяких State1, State2), то увидим:
behavior actor(event_based_actor* self)
{
    optional<Data1> data1;
    optional<Data2> data2;
    return {
        [](const Data1& d) {data1=d; if(data2) process(data1, data2);},
        [](const Data2& d) {data2=d; if(data1) process(data1, data2);}
    };
}

что код становится совершенно тривиальным и без всяких конечных автоматов. Более того, при такой же краткости, как вариант с future, он при этом заметно мощнее, т.к. никто не мешает добавить в него ещё одну строчку для параллельной обработки других сообщений.
Re[13]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 25.08.15 22:54
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

_>>Ты опять же говоришь про конечный автомат написанный ради обработки кривого распараллеливания. А не ради самой предметной задачи, где конечный автомат будет и даже в полностью однопоточном случае, скажем для реализации некого протокола, формата и т.п... И для этих целей я соответственно возьму данный http://www.boost.org/doc/libs/1_59_0/libs/msm/doc/HTML/ch03s04.html#d0e1462 инструмент. Ну а что касается реализации многопоточности, то я стараюсь её писать так, чтобы там конечные автоматы (не предметные) не возникали вовсе.

BZ>ну к примеру классическая задача на inversion of control — когда данные читаются блоками по 80 байт, а выдаваться должны по 60 байт (приводилась ещё в 60-х как пример удобства сопрограмм). думаю, здесь ничего удобней них и не придумаешь
BZ>то же относится к коду архзиватора, про котолрый я тебе говорил — представляем чтение файлов, разбиение на блоки и т.д. как отдельные сопрограммы/потоки и передаём данные через связывающие их потоки сообщений. в результате каждый из потоков выполняет отдельную несложную задачу
BZ>ну и везде так — проблема автоматов в том что они с другим кодом не сочетаются, как ты из них будешь строить сложную систему?

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

1. Конечные автоматы. Предлагаю исключить их из нашей дискуссии, т.к. в данной темке есть кажется только один человек, которые предпочитает реализовывать многопоточность/асинхронность с их помощью. И это не я и не ты (вроде бы).
2. Модель акторов. Вполне мне нравится и используется. Причём частенько даже не виде специальной библиотеки, а просто как концепция, скажем поверх обычных потоков. Да, и кстати говоря идея передачи данных через сообщения идеально легла на новую C++ концепцию семантики перемещения, позволяя получить быстродействие как при работе с общей памятью, при этом не нарушая безопасности, приносимой моделью акторов. Но это естественно не универсальный инструмент реализации многопоточности/асинхронности и в определённых случаях удобнее другие инструменты (типа parallel_for и т.п.).
3. Сопрограммы. Я с ними игрался какое-то время назад (естественно с нормальными, fullstack) и видел несколько любопытных применений. Например, как уже было указано в этой темке, они позволяют переделать синхронный код в асинхронный без его модификации. Скажем сделать из boost.spirit реактивный парсер. Однако применение их для повсеместной линеаризации асинхронного кода (как это сейчас модно в C#) мне кажется не очень хорошей практикой. Та же модель акторов лишь немного уступает в краткости кода, но зато намного превосходит в его понятности.

_>>Ну и да, код удобнее resp = await ask() очевидно есть. Это resp = ask().

BZ>ты просто переносишь проблему внутрь ask(). а как она будет реализована? через описание конечного автомата в виде массива переходов состояний? так await куда проще

Нет, речь шла совсем о другом. В общем если в начале не указать в каком месте кода и в какой момент времени нам необходим resp, то весь разговор будет бессмыслен. Т.к. существуют десятки разных вариантов этих условий и для каждого будут наиболее оптимальны свои решения.
Re[14]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 25.08.15 23:00
Оценка:
Здравствуйте, alex_public, Вы писали:

_>1. Конечные автоматы. Предлагаю исключить их из нашей дискуссии, т.к. в данной темке есть кажется только один человек, которые предпочитает реализовывать многопоточность/асинхронность с их помощью. И это не я и не ты (вроде бы).


этот человек — MS. ты похоже не в курсе async/await в c# и msvc2015
Люди, я люблю вас! Будьте бдительны!!!
Re[11]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 25.08.15 23:30
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

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

BZ>нет, думаю это вообще два разных вопроса. первое — это модель переключения между потоками исполнения: потоки ОС, зелёные потоки, сопрограммы двух видов. второе — это модель их взаимодействия: акторы, графы данных, разделяемая память. соответственно, пул потоков — это лишь механизм параллельного вполнения, а акторы или графы данных прекрасно могут работать поврех них как и любого другого механизма

Здесь подразумевалась разделяемая память. )
Re[13]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 26.08.15 08:46
Оценка:
Здравствуйте, Sinix, Вы писали:

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


а хоть где-нибудь они вообще реализованы?
Люди, я люблю вас! Будьте бдительны!!!
Re[14]: Об очередном антипаттерне. Модель акторов.
От: Sinix  
Дата: 26.08.15 09:16
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

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


BZ>а хоть где-нибудь они вообще реализованы?

Эрланг, MS orleans, с натяжкой скала.
Плюс куча невыстреливших прототипов внутри MS research. Как минимум in-out contracts в Singularity и COmega/Axum/Ms robotics CCR.
Re[15]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 26.08.15 09:46
Оценка:
Здравствуйте, Sinix, Вы писали:

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

BZ>>а хоть где-нибудь они вообще реализованы?
S>Эрланг

смотрим:
> Акторы предполагают, во-первых, декларативное описание ч/з комбинацию состояние-входы-выходы.

этого в эрланге нет

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


этого тоже. таким образом, эрланг — неподходящий язык для использования акторов?
Люди, я люблю вас! Будьте бдительны!!!
Re[16]: Об очередном антипаттерне. Модель акторов.
От: Sinix  
Дата: 26.08.15 10:17
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

>> Акторы предполагают, во-первых, декларативное описание ч/з комбинацию состояние-входы-выходы.

BZ>этого в эрланге нет
Весь gen_event же.

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

Слышал как минимум про две софтины с общим кодом на эрланге для сервера и клиента на мобильнике. Если не врут, то поддержка андроида в Erlang/OTP прям из коробки была. Так что с натяжкой, но есть.
Re[17]: Об очередном антипаттерне. Модель акторов.
От: Sinix  
Дата: 26.08.15 10:21
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Скорее всего бОльшая часть программ тупо перестанет работать, потому что stackfull, внезапно, дает возможность, ну например, повторно войти в принципиально нереэнтерабельный участок кода.

Так это не столько к await, сколько ко всему коду, написанному без учёта реэнтерабельности.
Ну, т.е. поломается и без await-а
Re[17]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 26.08.15 11:01
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Скорее всего бОльшая часть программ тупо перестанет работать, потому что stackfull, внезапно, дает возможность, ну например, повторно войти в принципиально нереэнтерабельный участок кода. Ну вот блокирующее чтение из стрима. Глобальные ресурсы пока еще никто не отменял. Опаньки !


для этого нужно чтобы прикладной код ещё и заходил туда. сейчас он этого не делает и автоматом делать этого не станет. с таким же успехом иожно ожидать что добавление библиотеки Thread поломает старые однопоточные программы, даже если они её не вызывают
Люди, я люблю вас! Будьте бдительны!!!
Re[14]: Об очередном антипаттерне. Модель акторов.
От: Sharov Россия  
Дата: 26.08.15 11:09
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Конечный автомат — это полезный инструмент, но не имеющий никакого отношения к вопросам многопоточности, асинхронного кода, сопрограммам и т.п. )


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

Можно открыть эту книгу на восьмой главе. Или вот, например.
Кодом людям нужно помогать!
Re[18]: Об очередном антипаттерне. Модель акторов.
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 26.08.15 12:38
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

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


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

Теперь фокус — ктото взял и запустил твой код во втором потоке. Вопрос — чего ожидать.
Собтсвенно непонятно, почему в случае со Stackfull короутинами будет как то иначе ?
Re[19]: Об очередном антипаттерне. Модель акторов.
От: BulatZiganshin  
Дата: 26.08.15 12:53
Оценка:
Здравствуйте, Ikemefula, Вы писали:

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


I>Наоборот, именно это прикладной код и делает. От тебя мало что будет зависеть. Вот ты ожидаешь, что чтение из стрима блокирующее, у тебя один поток, потому упрощаешь себе жизнь. Скажем, в однозадачном приложении никто не утруждает себя телодвижениями "а вдруг через 5 лет здесь появится многозадачность"


I>Теперь фокус — ктото взял и запустил твой код во втором потоке. Вопрос — чего ожидать.

I>Собтсвенно непонятно, почему в случае со Stackfull короутинами будет как то иначе ?

потому что код и так уже работает во втором потоке. только теперь короутина стала поддерживать переключение из вложенных выховов. но сами по себе они от добавления этой поддержки не появятся
Люди, я люблю вас! Будьте бдительны!!!
Re[20]: Об очередном антипаттерне. Модель акторов.
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 26.08.15 13:14
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

I>>Теперь фокус — ктото взял и запустил твой код во втором потоке. Вопрос — чего ожидать.

I>>Собтсвенно непонятно, почему в случае со Stackfull короутинами будет как то иначе ?

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


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

>но сами по себе они от добавления этой поддержки не появятся


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

твой код вызывает сторонний фремворк который вызывает твой стрим. Ты, внезапно, ввел короутины и стрим стал неблокирующим.
Вопрос — откуда фремворку знать, что надо как то иначе работать с глобальными ресурсами ?
Re[17]: Об очередном антипаттерне. Модель акторов.
От: neFormal Россия  
Дата: 26.08.15 17:45
Оценка:
Здравствуйте, Sinix, Вы писали:

>>> Акторы предполагают, во-первых, декларативное описание ч/з комбинацию состояние-входы-выходы.

BZ>>этого в эрланге нет
S>Весь gen_event же.

т.е. эрланговские акторы без gen_event'а уже не акторы?

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

S>Слышал как минимум про две софтины с общим кодом на эрланге для сервера и клиента на мобильнике. Если не врут, то поддержка андроида в Erlang/OTP прям из коробки была. Так что с натяжкой, но есть.

я погуглил, но там что-то совсем мутное.
можешь найти адекватный пример?
...coding for chaos...
Re[18]: Об очередном антипаттерне. Модель акторов.
От: Sinix  
Дата: 26.08.15 19:41
Оценка:
Здравствуйте, neFormal, Вы писали:


F>т.е. эрланговские акторы без gen_event'а уже не акторы?

Нет конечно Но НЯП, это как "самурай без меча подобен самураю с мечом, но только без меча". Есть-то оно есть, толку-то?
И на эту тему лучше реальных эрланговодов поспрашивать, я скорее свечку держал
Если ничего не перепутал, из отметившихся в ветке, это как минимум Mamut.

F>я погуглил, но там что-то совсем мутное.

F>можешь найти адекватный пример?
Неа, про эрланг на андроиде с чужих слов, гугль находит что-то типа такого, не больше.
Re[14]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 28.08.15 20:27
Оценка:
Здравствуйте, alex_public, Вы писали:

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


_>>>Конечно не представляю. ))) Я же не расставляю конечные автоматы по всему коду и по любому поводу.

LP>>Я тебе верю. Ты похоже вообще слабо представляешь, что такое конечный автомат.

_>Конечный автомат — это полезный инструмент, но не имеющий никакого отношения к вопросам многопоточности, асинхронного кода, сопрограммам и т.п. )


До такой степени не имеет, что _любой_ актор является конечным автоматом просто по определению.

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

Итак, имеем:
1. Актор имеет состояние
2. Актор принимает входные символы (сообщения)
3. При поступлении сообщения актор переходит в новое состояние, которое зависит от поступившего сообщения и текущего состояния

Если заменить в этих пунктах слово "актор" на "конечный автомат", получим букварное определение КА.

Это что касается теории. На практике _каждая_ известная мне реализация акторов имеет в своем составе ДСЛ для определения конечного автомата
Вот для AKKA:
http://doc.akka.io/docs/akka/snapshot/scala/fsm.html

Использование конечного автомата для описания поведения актора является _рекомендуемым_ для akka.
Другая известная в мире С++ реализация акторов SObjectizer (разрабатываемая eao из этого форума) также использует конечные автоматы для реализации акторов.

_>Вся указанная логика легко кодируется в несколько строк:

_>
_>BOOST_MSM_EUML_TRANSITION_TABLE(( 
_>    State1 + Response1 [state_(data1)=event(data1),!!state_(data2)] / (process, someCommonForState1State2Processing) == State1_Processed,
_>    State1 + Response2 [state_(data2)=event(data2),!!state_(data1)] / (process, someCommonForState1State2Processing) == State1_Processed,
_>    State2 + Response1 / (doAnotherProcessing, someCommonForState1State2Processing) == State2_Processed
_>),transition_table)
_>


Я пробовал разные DSL для описания конечных автоматов. В java их вагон. Однако, другие разработчики,как это не странно, были не в восторге от этих фреймворков. Уверяю тебя, для человека, который будет поддерживать код, который ты привел, изначальная форма при всей ее уродливости намного понятнее. Испробовано несколько раз.

_>Но только при условие, что State1, State1_Processed, State2, State2_Processed — это состояния полученные из предметной области. А не очередные последствия кривой многопоточности — тогда и от них надо избавляться.


Ну разумеется, это состояния из предметной области. Разве ты видишь, что они непосредственно связаны с запросами?

_>Причём самое интересно, что к теме акторов это всё уже не имеет никакого отношения. Все эти предметные состояния и конечные автоматы были показаны только для смешного впаривания. Потому как если мы посмотрим на предлагаемый вариант работы без акторов, то увидим, что там пропадают не только никчемные состояния, появившиеся вроде как из-за акторов (а на самом деле из-за криворукости), но и предметные. Т.е. эти два примера кода не имеют между собой ничего общего.


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

_>Если же мы попробуем написать на акторах аналог предложенного кода на future (т.е. без всяких State1, State2), то увидим:

_>
_>behavior actor(event_based_actor* self)
_>{
_>    optional<Data1> data1;
_>    optional<Data2> data2;
_>    return {
_>        [](const Data1& d) {data1=d; if(data2) process(data1, data2);},
_>        [](const Data2& d) {data2=d; if(data1) process(data1, data2);}
_>    };
_>}
_>


Даже в случае предельного упрощения ситуации путем выкидывания состояний, этот код все равно не правильный. Если Data1 придет без запроса, сообщение не будет обработано. Это между прочим тривиальнейший случай и встречается на каждом шагу. Приведу пример, приближенный к реальному, — рассмотрим два актора, первый — комната для онлайн игры, второй — игра в комнате. Комната может остановить игру путем посылки сообщения игре StopGame и получит в ответ от игры после остановки GameStopped. При этом игра может остановиться сама по себе (например, игру покинули все игроки или просто нашелся победитель). В этом случае GameStopped придет по событию остановки игры, без всякого запроса StopGame со стороны комнаты. Эти случае должны быть обработаны совершенно различным способом, потому что в случае остановки игры по инициативе комнаты комната должна после получения сообщения GameStopped разослать системные сообщения о принудительной остановке игры и произвести запись в лог (ибо это не характерная ситуация — игроки не смогли доигать до конца). В случае самостоятельной остановки игры комната просто удалит игру. Кстати, даже на таком примитивном примере можно продемонстрировать, каким образом может появиться зависимость от состояний. Комната может затребовать остановку игры по самым различным причинам. Рассмотрим две причины — удаление комнаты (очевидно, перед удалением игра в ней должна быть остановлена) и остановку сервера (сервер рассылает всем комнатам сообщения деинициализации). Обработка сообщения GameStopped зависит от причины остановки! Если остановка игры была вызвана удалением комнаты, необходимо после получения подтверждения об остановке игры и записей в лог подготовить комнату к удалению и послать сообщение серверу, что комната готова к удалению. В случае остановки сервера нужно просто произвести деинициализацию. Это один в один случай из моего примера. В реальных акторах совокупность возможных состояний и сообщений может быть таковой, что без формализации актора в виде конечного автомата будет потерян всякий контроль над происходящим. Повторюсь, мне не пришлось бы тебе это объяснять, если бы у тебя был хотя бы минимальный опыт написания акторов. Я занимаюсь этим уже два года, за которые успел повидать разные сценарии работы с акторами, как правильные,так и неправильные, поэтому могу делать определенные выводы о том, как акторы писать можно, а как нельзя. Так вот, большинство правильно написанных акторов были реализованы при помощи конечных автоматов. Поэтому я могу понять, почему разработчики акторных фреймворков всегда дополняют инструментарий дополнительной поддержкой конечных автоматов.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[13]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 28.08.15 20:32
Оценка:
Здравствуйте, Sinix, Вы писали:

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



S>>>Разумеется, это не значит, что на голый await стоит натягивать акторы.

LP>>В Unity3d натянули на yield return null. Правда, не акторы, а автоматный код скриптов.
S>Угу, это не совсем акторы.

S>Акторы предполагают, во-первых, декларативное описание ч/з комбинацию состояние-входы-выходы.


Декларативное описание? Это где такое требование?

S>Во-вторых, свою модель вычислений (с immutable-данными + pure-функциями).


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

S>А, да, всю эту кухню конечно можно спрятать за await, но менее главной она от этого не станет.


await вообще параллельно к самой концепции актора. Это способ упрощения его реализации путем линеаризации кода. Я ведь приводил пример с актором Player ниже по ветке.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[19]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 28.08.15 20:34
Оценка:
Здравствуйте, Mamut, Вы писали:

F>>т.е. эрланговские акторы без gen_event'а уже не акторы?


M>Акторы, акторы.


M>Главное отличие Эрланга — прагматичный подход. Если теория говорит, что «функциональный язык должен быть чистым», а «акторы должны декларативно задаваться», Эрланг смотрит на это с легким недоумением и презрением, а потом реализует то, что наиболее рпактично в реальном мире.


Актор не должен декларативно задаваться. Впрочем, под декларативностью люди понимают разные вещи, для кого-то и ФП декларативно.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[13]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 28.08.15 20:36
Оценка:
Здравствуйте, neFormal, Вы писали:

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


LP>>Как можно видеть конечный автомат при помощи сопрограмм реализован без введения трех явных состояний.


F>скорее над этим находятся другие состояния поведения.


Эти три состояния тоже неявно присутствуют. Их втыкает языковая реализация yield return.

F>а промежуточные состояния атаки часто и не нужны.


Это просто пример. Кстати, почему не нужны, атака может быть серией ударов.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[14]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 28.08.15 20:52
Оценка:
Здравствуйте, so5team, Вы писали:

S>Может быть вовсе и не так. А вот так:

S>
S>// Описание связей.
S>fsmState.in(WAIT_FOR_RESPONSE1).event(calc1);
S>fsmState.in(WAIT_FOR_RESPONSE2).event(calc2);
S>fsmState.in(NO_REQUEST).event(processEvent);
S>


S>Т.е. обслуживание конечного автомата актора является одной из задач фреймворка, реализующего Actor Model. То, что в Akka/Scala этого нет не означает ущербности ActorModel.


В акка как раз это есть. Только конечный автомат как его не украшай, останется конечным автоматом. Если бы накладные расходы от КА можно было бы нивелировать красивым фреймворком, весь геймдев не двигался бы от КА к behaviour tree и сопрограммам.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[14]: Об очередном антипаттерне. Модель акторов.
От: neFormal Россия  
Дата: 28.08.15 21:31
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>Эти три состояния тоже неявно присутствуют. Их втыкает языковая реализация yield return.

LP>Это просто пример. Кстати, почему не нужны, атака может быть серией ударов.

это уже следующий уровень вложенности. на каждом только то, что необходимо для этого действия. так проще.
в верхние состояния тащить это нет смысла.
...coding for chaos...
Re[16]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 29.08.15 13:09
Оценка:
Здравствуйте, neFormal, Вы писали:

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


LP>>До такой степени не имеет, что _любой_ актор является конечным автоматом просто по определению.


F>обоснования?


Обоснование там же.

F>актор может не менять поведение в зависимости от состояния и при этом оставаться актором. а может и состояния не менять.


Конечно, может. Но подавляющее кол-во акторов таки меняют. И не нужно кивать на неправильное проектирование, я видел достаточно акторного кода, написанного хорошими специалистами в многопоточности.

LP>>Приведу пример, приближенный к реальному, — рассмотрим два актора, первый — комната для онлайн игры, второй — игра в комнате. Комната может остановить игру путем посылки сообщения игре StopGame и получит в ответ от игры после остановки GameStopped. При этом игра может остановиться сама по себе (например, игру покинули все игроки или просто нашелся победитель). В этом случае GameStopped придет по событию остановки игры, без всякого запроса StopGame со стороны комнаты. Эти случае должны быть обработаны совершенно различным способом, потому что в случае остановки игры по инициативе комнаты комната должна после получения сообщения GameStopped разослать системные сообщения о принудительной остановке игры и произвести запись в лог (ибо это не характерная ситуация — игроки не смогли доигать до конца).


F>во всех случаях достаточно сказать серверу ойвсё(успешно/ниочинь, результаты);


LP>>В случае самостоятельной остановки игры комната просто удалит игру.


F>игра удаляется в любом случае.


Разумеется. Об этом и речь — есть общая част логики, есть раздельная.

LP>>Рассмотрим две причины — удаление комнаты (очевидно, перед удалением игра в ней должна быть остановлена) и остановку сервера (сервер рассылает всем комнатам сообщения деинициализации). Обработка сообщения GameStopped зависит от причины остановки! Если остановка игры была вызвана удалением комнаты, необходимо после получения подтверждения об остановке игры и записей в лог подготовить комнату к удалению и послать сообщение серверу, что комната готова к удалению.

LP>>В случае остановки сервера нужно просто произвести деинициализацию.
F>во всех случаях достаточно облить бензином и поджечь.

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

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

F>почему тогда у тебя получается так сложно?

Приведенный пример взят из успешного проекта с десятилетней историей, написанный специалистами в многопоточном программировании, сделанный на их же собственном акторном фреймворке, написанном специально для проекта.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[16]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 29.08.15 13:14
Оценка:
Здравствуйте, Mamut, Вы писали:

LP>>Это что касается теории. На практике _каждая_ известная мне реализация акторов имеет в своем составе ДСЛ для определения конечного автомата

LP>>Вот для AKKA:
LP>>http://doc.akka.io/docs/akka/snapshot/scala/fsm.html

M>1. Какие тебе реализации акторов известны?


В основном, внутренние реализации, специфичные для проектов. Видел две более-менее удачные реализации для С++ и одну — для java.
Из публичных мне известны akka и sobjectizer

M>2. fsm в akka напрямую взят из библиотеки Erlang'а, потому что создание конечных автоматов является часто встречающейся задачей, и для нее в Erlang'е сделано общее решение. Так же в эрланге есть общие решения для серверов, событий и супервизоров: потому что это — часто встречающиеся паттерны, и почему бы не реализовать что-то, часто встречающееся.


M>И да, (gen_)fsm — самый редко используемых из всех.


Так не понял, часто используемый или редко используемый?
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[17]: Об очередном антипаттерне. Модель акторов.
От: neFormal Россия  
Дата: 29.08.15 13:36
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>>>До такой степени не имеет, что _любой_ актор является конечным автоматом просто по определению.

F>>обоснования?
LP>Обоснование там же.

нет там его.

F>>актор может не менять поведение в зависимости от состояния и при этом оставаться актором. а может и состояния не менять.

LP>Конечно, может.

и к чему тогда был пассаж про "КА по определению" ?

LP>Но подавляющее кол-во акторов таки меняют.


не вижу такого. покажи.

LP>И не нужно кивать на неправильное проектирование, я видел достаточно акторного кода, написанного хорошими специалистами в многопоточности.


ммм... и что с того?

LP>>>В случае самостоятельной остановки игры комната просто удалит игру.

F>>игра удаляется в любом случае.
LP>Разумеется. Об этом и речь — есть общая част логики, есть раздельная.

нет никакой необходимости разделять. удалилась и удалилась.

F>>во всех случаях достаточно облить бензином и поджечь.

LP>Приведи пример реализации описанного сценария. Только с учетом того, что комната и игра являются акторами.

я же написал. в случае любого завершения игры она просто присылает результаты со статусом завершения.

F>>почему тогда у тебя получается так сложно?

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

печально звучит.
...coding for chaos...
Re[17]: Об очередном антипаттерне. Модель акторов.
От: Mamut Швеция http://dmitriid.com
Дата: 30.08.15 08:31
Оценка:
M>>2. fsm в akka напрямую взят из библиотеки Erlang'а, потому что создание конечных автоматов является часто встречающейся задачей, и для нее в Erlang'е сделано общее решение. Так же в эрланге есть общие решения для серверов, событий и супервизоров: потому что это — часто встречающиеся паттерны, и почему бы не реализовать что-то, часто встречающееся.

M>>И да, (gen_)fsm — самый редко используемых из всех.


LP>Так не понял, часто используемый или редко используемый?


Самый редко используемый из часто используемых. То есть так: создание FSM — это достаточно общая задача, чтобы сделать для нее общее решение. Но из всех общих решений FSM — самый редко используемый. gen_server используется чаще на несколько десятичных порядков, например.

FSM нужен для создания FSM. Сказки про то, что каждый актор — это FSM оставим сказочникам.

ЗЫ. Скачал тут себе распределенную базу данных Riak, реализованную на Erlang'е. Скачал все ее зависимости, тоже на Erlang'е. То есть, казалось бы, код, в котором FSM просто обязан быть. И даже тут fsm — на последнем месте.

> fgrep -R "-behaviour(gen_fsm" . | wc
      18
> fgrep -R "-behaviour(gen_event" . | wc
      19
> fgrep -R "-behaviour(supervisor" . | wc
      71
> fgrep -R "-behaviour(gen_server" . | wc
      82
> fgrep -R "spawn(" . | wc
     157


Последняя строчка — это spawn, создание новых процессов вообще без каких-либо generic обвязок. И ничего, никто без fsm не умер.


dmitriid.comGitHubLinkedIn
Re[16]: Об очередном антипаттерне. Модель акторов.
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 22.01.16 04:54
Оценка:
Здравствуйте, alex_public, Вы писали:

_>>>Конечный автомат — это полезный инструмент, но не имеющий никакого отношения к вопросам многопоточности, асинхронного кода, сопрограммам и т.п. )

LP>>До такой степени не имеет, что _любой_ актор является конечным автоматом просто по определению.

_>Смотрю сюда https://ru.wikipedia.org/wiki/%D0%9C%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D0%B0%D0%BA%D1%82%D0%BE%D1%80%D0%BE%D0%B2 и не вижу ничего подобного.


Ты свою ссылку то открывал ? "выбрать тип поведения, которое будет использоваться для следующего сообщения в свой адрес.".

_>Самое забавное, что тот мой пример (с запуском скачивания файла в отдельном потоке и возврате результата через сообщение) вполне укладывается в определение по моей ссылке выше, но не имеет ничего общего с данными пунктами. )))


В чистом виде конечный автомат, только ты его пишешь обычным кодом.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.