Здравствуйте, Ikemefula, Вы писали:
I>Чем твой yield лучше await в таком случае ?
Ну так это оно и есть.))) Только await менее удобный и эффективный.
Вообще у нас какое-то странное обсуждение пошло. Давай я один раз опишу свою точку зрения на всё это, а ты скажешь согласен или нет. И так:
1. Существует нормальное многопоточное программирование, которое люди используют уже многие годы. Причём используется практические везде. И соответственно реализации этого есть практически во всех языках. В C++ это сейчас std::thread и std::future/std::async. В C# их аналоги это System.Threading.Thread и System.Threading.Tasks.Task.
2. Одним из частных случаев пункта 1 является программирование задачи по вычислению чего-то в отдельном потоке (с возможным контролем работы) и возврата значения в изначальный поток. Часто такое называет асинхронным кодом. Тривиально реализуется обычными же средствами. Например для C++ код с вызывающим потоком без цикла сообщений:
auto r=async(launch::async, []{return CalcSomething();});
DoAnother();
ProcessResult(r.get());
3 Существует такая довольно специфическая вещь как сопроцедуры, позволяющая иметь множественные точки входа во вроде бы линейный код. Реально полезное применение в основном в случае наличия очень большого числа параллельных задач, т.к. реализация подобного через обычные потоки уже весьма неэффективна. Так же может применяться для реализации "генераторов". В силу своей специфичности имеют реализации не во всех языках (реализацию от ОС не рассматриваем). В C++ реализация есть и даже не одна, а много разных. В том числе и наиболее эффективная (stackfull) из всех — Boost.Coroutine. Для C# тоже имеется своя реализация (await), причём встроенная в сам язык, но при этом весьма ограниченная и неэффективная.
4. Агрессивные евангелисты C#'а однажды (не так давно кстати) записав пункт 2 с помощью пункта 3 неожиданно "обнаружили" что:
— совершён очередной великий прорыв в программирование (гыгы)
— естественно не имеющий аналогов в других языках (гыгыгы)
— программировать асинхронный код удобнее именно так (ага, как же, только кривую архитектуру плодить)
— только теперь люди смогут заниматься настоящим асинхронное программированием (гыгы)
Вот такая картинка у меня. Есть возражения? )
P.S. Эх, и всё же куда так резко пропал gandjustas...
Здравствуйте, Grundik2, Вы писали:
G>Хочу поиграться с чем-нибудь, чтобы компилилось сразу в native код. Аналог C++'са, но не слишком экзотическое, малоизвестное или вымирающее. На ум приходит только D и Rust. Что порекомендуете?
Аналогов С++ не существует. И слава богу! :D
Из перечисленных я бы выбрал Go. Rust — слишком долго ждать стабильного релиза, язык сейчас сильно меняется. Go самый стабильный из всех вышеперечисленных, много всякого полезного барахла в стандартной библиотеке, очень приятный и простой язык, message passing + shared memory concurrency, очень клевый и крутой go tool, отличная документация, очень быстрые билды, возможность писать unsafe код, очень простой интероп с сишечкой.
Здравствуйте, alex_public, Вы писали:
I>>Чем твой yield лучше await в таком случае ?
_>Ну так это оно и есть.))) Только await менее удобный и эффективный.
Где именно потери эффективности ? Где больше удобства ?
_>2.
И вот что бы не городить такой мусор, придумали async/await.
_>3 Существует такая довольно специфическая вещь как сопроцедуры, позволяющая иметь множественные точки входа во вроде бы линейный код. Реально полезное применение в основном в случае наличия очень большого числа параллельных задач, т.к. реализация подобного через обычные потоки уже весьма неэффективна. Так же может применяться для реализации "генераторов". В силу своей специфичности имеют реализации не во всех языках (реализацию от ОС не рассматриваем). В C++ реализация есть и даже не одна, а много разных. В том числе и наиболее эффективная (stackfull) из всех — Boost.Coroutine. Для C# тоже имеется своя реализация (await), причём встроенная в сам язык, но при этом весьма ограниченная и неэффективная.
Правильно — stackfull короутины нужны именно для кооперативной многозадачности. А ты и EP рассказывали басни что де все шоколадно с асинхронщиной, стоит только насовать короутин куда попало.
await это не короутины, это поддержка асинхронных вычислений. Короутины просто используются для этого.
Ты путаешь два разных инструмента.
Ну и не ясно, как ты эффект меряешь.
_>4. Агрессивные евангелисты C#'а однажды (не так давно кстати) записав пункт 2 с помощью пункта 3 неожиданно "обнаружили" что: _> — совершён очередной великий прорыв в программирование (гыгы) _> — естественно не имеющий аналогов в других языках (гыгыгы) _> — программировать асинхронный код удобнее именно так (ага, как же, только кривую архитектуру плодить) _> — только теперь люди смогут заниматься настоящим асинхронное программированием (гыгы)
Предлагаешь обсудить твои фантазии ? Где ты видел высказыавния про великий прорыв, не имеющий аналогов и тд и тд ?
Здравствуйте, vdimas, Вы писали:
I>>Спасибо, капитан ! Я то думал, что короутины дотнета для которых прикручено N апи комбинаторов это кубики лего из которых можно собрать произвольную модель,
V>Увы, нельзя произвольную.
Берешь свои слова обратно что ли или сомневаешься в полноте по тьюрингу того же linq ?
I>>а на самом деле это апи комбинаторов, из которых можно собрать произвольную модель.
V>Только stackless, со всеми торчащими наружу кишками/модификаторами/ограничениями в сценариях и складыванием такого кода в глубокие "матрешки" дергающих друг друга конечных автоматов.
Я пока не увидел внятного примера, что бы кишки никуда не торчали в С++, то async понадобится, то await, то yield.
Что касается упаковывания внутрь фремворка, вот смотри, асинхронный код:
source.pipe(destination)
Никаких кишок не торчит, а код асинхронный. Надо полагать раз кишки не торчат, то такой результат и есть самая что ни есть круть на С++ ? А если я скажу, что это C# или джаваскрипт, что будешь делать ?
I>>Мне нужен пример не любых короутин, а stackfull. E.P. сделал много заявлений, но кроме синхронного кода ничего и не показал. Если бы alex_public не прикрыл его с фланга, был бы провал.
V>Нет там никакого синхронного кода.
Там все синхронное. Вообще все. Если короутины вызывают друг друга по кругу, вовсе не значит, что там чтото асинхронное появилось.
>Ты неоднократно прямо спросил кто и откуда вызывает короутины — тебе схематично показали,
Глаза раскрой — убираешь короутины и код продолжает работать. Это значит, что код тупо синхронный.
I>>Разумеется, а то первый же пример stackfull замораживал UI
V>Если ввод-вывод неблокирующий, то он никак не замораживает UI
Ты лучше возьми первый этот пример и покажи, как это он UI незамораживает.
I>>Правильно и все три работают без короутин.
V>Не надо валить всё в кучу. ))
Разговор начался с того, как все шоколадно в С++ благодаря особым короутинам.
V>Это модели диспетчеризации событий/задач, отличающиеся используемым низлежащим АПИ ОС. А то, что некая задача является "короутиной", диспетчеру должно быть вообще до фени. Пусть выгребает из очереди некий абстрактный Task и запускает его. Короутина — это уже нечто более высокоуровневое, это трюк для выпрямления прикладного автоматного/событийного кода в якобы линейный.
Правильно — якобы. Кишки будут торчать и там и там, вопрос только в наличии поддержки компилятора.
Здравствуйте, Lazin, Вы писали:
L>Здравствуйте, Grundik2, Вы писали:
G>>Хочу поиграться с чем-нибудь, чтобы компилилось сразу в native код. Аналог C++'са, но не слишком экзотическое, малоизвестное или вымирающее. На ум приходит только D и Rust. Что порекомендуете?
L>Аналогов С++ не существует. И слава богу! :D
Здравствуйте, Ikemefula, Вы писали:
I>Где именно потери эффективности ? Где больше удобства ?
Так писали же уже...
По эффективности: у C# реализации будет O(N) по стеку, вместо O(1)
По удобству: в C# реализации надо модифицировать код (как минимум расставлять async) на всех уровнях стека.
I>И вот что бы не городить такой мусор, придумали async/await.
Нуу а на мой взгляд это async/await мусор, т.к. ведёт к кривой архитектуре.
I>Правильно — stackfull короутины нужны именно для кооперативной многозадачности. А ты и EP рассказывали басни что де все шоколадно с асинхронщиной, стоит только насовать короутин куда попало.
Так верно и то и другое. Главное предназначение сопроцедур как раз в реализации "многозадачности без потоков" (кстати, а с этим в C# вообще тухло, да?). Но как мы видим по тому же async/await из C# их можно приспособить и для всяких извращений. Соответственно если программист на C++ всё же захочет использовать сомнительную архитектуру типа async/await, то с учётом наличия Boost.Coroutines он сможет это сделать в десяток строчек кода.
Кстати, я же ещё не показывал тут вариант нормальной многопоточной асинхронности с короутинами. Тогда уж покажу один из вариантов (набросал за пару минут), что бы не быть голословным. Значит такой код:
void TestAsync(int n)
{
BEGIN_ASYNC
wcout<<L"Запускаем асинхронное из потока "<<this_thread::get_id()<<endl;
auto r=await_async([&]{
this_thread::sleep_for(chrono::milliseconds(500));
wostringstream res;
res<<L"Завершена работа в потоке "<<this_thread::get_id()<<L" над данными "<<n;
return res.str();
});
wcout<<L"Показываем результат в потоке "<<this_thread::get_id()<<L": "<<r<<endl;
END_ASYNC
}
TestAsync(12345);
TestAsync(67890);
wcout<<L"Показываем MessageBox из потока "<<this_thread::get_id()<<endl;
MessageBox(L"Тест!");
wcout<<L"MessageBox закрыт в потоке "<<this_thread::get_id()<<endl;
Выводит следующее:
Запускаем асинхронное из потока 1
Запускаем асинхронное из потока 1
Показываем MessageBox из потока 1
Показываем результат в потоке 1: Завершена работа в потоке 2 над данными 12345
Показываем результат в потоке 1: Завершена работа в потоке 3 над данными 67890
MessageBox закрыт в потоке 1
Ну и реализация:
using __Coro=boost::coroutines::coroutine<void()>;
template<typename L> auto __await_async(const __Coro* coro, __Coro::caller_type& yield, L lambda)->decltype(lambda())
{
auto f=async(launch::async, [=](){
auto r=lambda();
App.PostMessage(coro);
return r;
});
yield();
return f.get();
}
void RunAsync(Event& event)
{
__Coro* c=event.Get<__Coro*>();
(*c)();
if(!*c) delete c;
}
#define BEGIN_ASYNC { __Coro* __coro=new __Coro; *__coro=__Coro([=](__Coro::caller_type& __yield){
#define END_ASYNC });}
#define await_async(l) __await_async(__coro, __yield, l)
...
void App::OnAsyncMessage(Event& event) {RunAsync(event);}//<-один обработчик на всё приложение
Причём эта реализация в десяток строк ещё и заметно эффективнее (фирменный знак C++) C#'ой по накладным расходам. Вот такие дела.
I>await это не короутины, это поддержка асинхронных вычислений. Короутины просто используются для этого. I>Ты путаешь два разных инструмента.
Ну да, правильно. Так просто асинхронные вычисления (без сахара от сопроцедур) есть давным давно и наверное во всех языках. ))) Так что здесь мы обсуждаем именно C#'ий сахар, а он как раз основан на сопроцедурах.
I>Предлагаешь обсудить твои фантазии ? Где ты видел высказыавния про великий прорыв, не имеющий аналогов и тд и тд ?
Это была ирония, но она не особо отличалась от настроя некоторых товарищей в этой темке. Ну и вообще для агрессивных евангелистов C# это обычно дело. Помнится до async/await у нас был прорыв с LINQ, а перед этим ещё что-то (а ну да, DLL hell же)...
Здравствуйте, Ikemefula, Вы писали:
I>>>Спасибо, капитан ! Я то думал, что короутины дотнета для которых прикручено N апи комбинаторов это кубики лего из которых можно собрать произвольную модель, V>>Увы, нельзя произвольную. I>Берешь свои слова обратно что ли или сомневаешься в полноте по тьюрингу того же linq ?
Конечно не беру, если мы все еще об встроенном async. Ручками я тебе что хошь накручу, ес-но, благо интероп и ансейф дотнета в "шаговой доступности".
I>>>а на самом деле это апи комбинаторов, из которых можно собрать произвольную модель.
V>>Только stackless, со всеми торчащими наружу кишками/модификаторами/ограничениями в сценариях и складыванием такого кода в глубокие "матрешки" дергающих друг друга конечных автоматов.
I>Я пока не увидел внятного примера, что бы кишки никуда не торчали в С++, то async понадобится, то await, то yield.
В сигнатуре ниче не торчит. Нет ограничений на уровне контрактов.
I>Что касается упаковывания внутрь фремворка, вот смотри, асинхронный код:
I>
I>source.pipe(destination)
I>
В том-то и дело, что под дотнетный async надо было разработать еще один фреймворк, помимо имеющегося под обычные коллекции, Rx или Linq + связку с этими имеющимися
I>Никаких кишок не торчит, а код асинхронный.
Любая неблокирующая операция укладывается в любую асинхронную модель. Асинхронаня — значит отложенная. Адекватная асинхронная модель пытается что-то делать в неблокирующем режиме, в случае неудачи — "откладывает" операцию. (Даже если в публичном АПИ это выглядит не так, "унутре" это именно так)
Вот эта строчка "отложения" операции, которую ты показал, она вообще ни о чем в данном споре.
I>Надо полагать раз кишки не торчат, то такой результат и есть самая что ни есть круть на С++ ? А если я скажу, что это C# или джаваскрипт, что будешь делать ?
Чтобы кишки торчали, нужен контракт с торчащими кишками. Я не увидел там контракта.
I>Там все синхронное. Вообще все. Если короутины вызывают друг друга по кругу, вовсе не значит, что там чтото асинхронное появилось.
Значит ты не понимаешь, что такое асинхронность.
>>Ты неоднократно прямо спросил кто и откуда вызывает короутины — тебе схематично показали, I>Глаза раскрой — убираешь короутины и код продолжает работать. Это значит, что код тупо синхронный.
Блин, опять ты все в кучу!!! Короутины НЕ НУЖНЫ для асинхронности. Вообще. Они нужны для выпрямления событийного кода в якобы линейный. Причем, эта фишка может использоваться не обязательно в асинхронном коде, она может быть использована для кооперативной многозадачности. Так же, как пойдет для этого await или enumerator-yield в дотнете (одинаковая хрень, по сути, но требующая независимых языковых конструкций из-за прибитости гвоздями).
V>>Если ввод-вывод неблокирующий, то он никак не замораживает UI I>Ты лучше возьми первый этот пример и покажи, как это он UI незамораживает.
Тут было много примеров, я ворвался посреди спора, кинь точной ссылкой плиз.
I>>>Правильно и все три работают без короутин.
V>>Не надо валить всё в кучу. ))
I>Разговор начался с того, как все шоколадно в С++ благодаря особым короутинам.
Конечно, ведь начали хвалить async в C#, поэтому речь зашла о короутинах в C++. В дотнете отродясь была асинхронность и без всякого async. Ты просто пытаешься путать синт. сахар с принципом работы.
V>>Это модели диспетчеризации событий/задач, отличающиеся используемым низлежащим АПИ ОС. А то, что некая задача является "короутиной", диспетчеру должно быть вообще до фени. Пусть выгребает из очереди некий абстрактный Task и запускает его. Короутина — это уже нечто более высокоуровневое, это трюк для выпрямления прикладного автоматного/событийного кода в якобы линейный.
I>Правильно — якобы. Кишки будут торчать и там и там, вопрос только в наличии поддержки компилятора.
Да вот, увы, сигнатура await торчит так уж торчит. Да и вообще. Весь спор можно было сворачивать сразу после поста о stackless/stackfull, всё и так понятно. Две модели, два подхода.
Здравствуйте, vdimas, Вы писали:
V>>>Увы, нельзя произвольную. I>>Берешь свои слова обратно что ли или сомневаешься в полноте по тьюрингу того же linq ?
V>Конечно не беру, если мы все еще об встроенном async. Ручками я тебе что хошь накручу, ес-но, благо интероп и ансейф дотнета в "шаговой доступности".
То есть, не согласен, но ручками можно накрутить что угодно ? Не входит ли в это что угодно "произвольная модель" или как ?
I>>Я пока не увидел внятного примера, что бы кишки никуда не торчали в С++, то async понадобится, то await, то yield.
V>В сигнатуре ниче не торчит. Нет ограничений на уровне контрактов.
И это неправильно. В сигнатуре должно быть указание, как можно вызывать метод и чего от этого можно ожидать.
V>В том-то и дело, что под дотнетный async надо было разработать еще один фреймворк, помимо имеющегося под обычные коллекции, Rx или Linq + связку с этими имеющимися
А как ты хотел, что бы появились плюшки в языке и фремворки внезапно стали их поддерживать ?
I>>Никаких кишок не торчит, а код асинхронный.
V>Вот эта строчка "отложения" операции, которую ты показал, она вообще ни о чем в данном споре.
Ну ведь говорили что должны торчать какие то кишки. А тут ничего не торчит.
V>Чтобы кишки торчали, нужен контракт с торчащими кишками. Я не увидел там контракта.
Ну да, а у меня, прикинь, никакого async не торчит, вот незадача то.
V>Блин, опять ты все в кучу!!! Короутины НЕ НУЖНЫ для асинхронности.
Я уже десятый раз об этом и говорю.
V>Вообще. Они нужны для выпрямления событийного кода в якобы линейный.
"якобы". О том, что это якобы как раз и должна сообщать сигнатура.
>Ты лучше возьми первый этот пример и покажи, как это он UI незамораживает.
V>Тут было много примеров, я ворвался посреди спора, кинь точной ссылкой плиз.
Ищи по getline
I>>Разговор начался с того, как все шоколадно в С++ благодаря особым короутинам.
V>Конечно, ведь начали хвалить async в C#, поэтому речь зашла о короутинах в C++. В дотнете отродясь была асинхронность и без всякого async. Ты просто пытаешься путать синт. сахар с принципом работы.
Вообще говоря искали альтернативы С++, потому резонно возник вопрос про асинхронщину.
I>>Правильно — якобы. Кишки будут торчать и там и там, вопрос только в наличии поддержки компилятора.
V>Да вот, увы, сигнатура await торчит так уж торчит. Да и вообще. Весь спор можно было сворачивать сразу после поста о stackless/stackfull, всё и так понятно. Две модели, два подхода.
Здравствуйте, alex_public, Вы писали:
_>По эффективности: у C# реализации будет O(N) по стеку, вместо O(1)
Это копейки, потому что в асинхронщине основные издержки на порядки больше.
_>По удобству: в C# реализации надо модифицировать код (как минимум расставлять async) на всех уровнях стека.
Модифицировать код надо там, где тебе нужно ожидание. Тебя это пугает ?
I>>И вот что бы не городить такой мусор, придумали async/await. _>Нуу а на мой взгляд это async/await мусор, т.к. ведёт к кривой архитектуре.
Кривая архитектура, это когда переходы непойми где делаются. А когда код легко майнтейнить, это хорошая архитектура. async упрощает майнтенанс.
_>Причём эта реализация в десяток строк ещё и заметно эффективнее (фирменный знак C++) C#'ой по накладным расходам. Вот такие дела.
Эффективность нужно мерять в конкретной задаче, а не в синтетике. Если реальная задача это будет чтото навроде скачивания, работы с файловой системой и тд, то все твои эффективности ничего не стоят.
_>Это была ирония, но она не особо отличалась от настроя некоторых товарищей в этой темке. Ну и вообще для агрессивных евангелистов C# это обычно дело. Помнится до async/await у нас был прорыв с LINQ, а перед этим ещё что-то (а ну да, DLL hell же)...
Linq это действительно прорыв. Главное не путать linq c query comprehension.
Здравствуйте, Ikemefula, Вы писали:
I>Эффективность нужно мерять в конкретной задаче, а не в синтетике. Если реальная задача это будет чтото навроде скачивания, работы с файловой системой и тд, то все твои эффективности ничего не стоят.
Да, правильно. Если бы для достижений этой эффективности надо было приложить усилия, то делать это вне реального кода под профайлером было бы глупо. Но весь фокус заключается в том, что делая этот пример я вообще не думал об эффективности, а реализовал именно самый простой и удобный способ. А он при этом автоматически стал ещё и эффективнее других — это как раз и есть классический "C++ стиль". )))
I>Linq это действительно прорыв. Главное не путать linq c query comprehension.
Гыгыгы
Ну разве что для людей считающих SQL идеалом DSL'ей для работы с коллекциями. )))
Здравствуйте, Ikemefula, Вы писали:
V>>Конечно не беру, если мы все еще об встроенном async. Ручками я тебе что хошь накручу, ес-но, благо интероп и ансейф дотнета в "шаговой доступности". I>То есть, не согласен, но ручками можно накрутить что угодно ? Не входит ли в это что угодно "произвольная модель" или как ?
Входит, ес-но, но поддержка её ср-вами языка — нет.
I>>>Я пока не увидел внятного примера, что бы кишки никуда не торчали в С++, то async понадобится, то await, то yield.
V>>В сигнатуре ниче не торчит. Нет ограничений на уровне контрактов.
I>И это неправильно. В сигнатуре должно быть указание, как можно вызывать метод и чего от этого можно ожидать.
Да никак. Обычно вызывай и все. Это именно настоящее "выпрямление" кода. Легковесная многозадачность, где ВНУТРИ метода стоят хинты, когда переключать задачу, как в виндах 3.x.
С т.з. вызывающего метода это обычный синхронный код, а вся асинхронность сугубо внешняя, как внешим является переключение потоков ОС по отношению к обычному коду на C#.
V>>В том-то и дело, что под дотнетный async надо было разработать еще один фреймворк, помимо имеющегося под обычные коллекции, Rx или Linq + связку с этими имеющимися I>А как ты хотел, что бы появились плюшки в языке и фремворки внезапно стали их поддерживать ?
Да. Программы для виндов 3.х прекрасно работали на win95, но уже с нормальной многозадачностью.
V>>Вот эта строчка "отложения" операции, которую ты показал, она вообще ни о чем в данном споре. I>Ну ведь говорили что должны торчать какие то кишки. А тут ничего не торчит.
Кишки могут торчать только в контрактах. А на уровне методов они должны быть. Конкретно тут кишки неблокирующей операции, но по этой строчке ничего нельзя сказать о коде. Асинхронность — это лишь название модели. Асинхронность может присутствовать и без поддержки языка.
V>>Чтобы кишки торчали, нужен контракт с торчащими кишками. Я не увидел там контракта. I>Ну да, а у меня, прикинь, никакого async не торчит, вот незадача то.
Торчит в том месте, где надо требует контракт. Давай полные сигнатуры и мы проверим, подходят ли типы.
V>>Блин, опять ты все в кучу!!! Короутины НЕ НУЖНЫ для асинхронности. I>Я уже десятый раз об этом и говорю.
Дык, async еще более не нужен хотя бы потому, что на порядки менее удобный.
V>>Вообще. Они нужны для выпрямления событийного кода в якобы линейный. I>"якобы". О том, что это якобы как раз и должна сообщать сигнатура.
Не должна. Просто так сделано в конкретном языке. Но это было не обязательно.
>>Ты лучше возьми первый этот пример и покажи, как это он UI незамораживает.
V>>Тут было много примеров, я ворвался посреди спора, кинь точной ссылкой плиз. I>Ищи по getline
Насколько я понял, там потом показали обертку над стандартной ф-ий с неблокирующими ветками.
I>>>Разговор начался с того, как все шоколадно в С++ благодаря особым короутинам.
V>>Конечно, ведь начали хвалить async в C#, поэтому речь зашла о короутинах в C++. В дотнете отродясь была асинхронность и без всякого async. Ты просто пытаешься путать синт. сахар с принципом работы.
I>Вообще говоря искали альтернативы С++, потому резонно возник вопрос про асинхронщину.
Но с ней в С++ всегда было лучше, чем в других ООП языках, именно из-за многообразия функциональных типов и именно из-за того, что вся асинхронщина, которая "в лоб" (без asyc), идет как IoC, в котором функциональный подход заруливает ООП. А с короутинами еще проще...
Но кста, есть либы с реализацией короутин-автоматов наподобие async. Единственно что, раньше переменные из замыканий надо было явно располагать в объекте-контексте, сейчас, уверен, появятся новые либы на плюсах, которые избавят от такого приседания.
Здравствуйте, alex_public, Вы писали:
I>>Эффективность нужно мерять в конкретной задаче, а не в синтетике. Если реальная задача это будет чтото навроде скачивания, работы с файловой системой и тд, то все твои эффективности ничего не стоят.
_>Да, правильно. Если бы для достижений этой эффективности надо было приложить усилия, то делать это вне реального кода под профайлером было бы глупо. Но весь фокус заключается в том, что делая этот пример я вообще не думал об эффективности, а реализовал именно самый простой и удобный способ. А он при этом автоматически стал ещё и эффективнее других — это как раз и есть классический "C++ стиль". )))
Мне интересно, как ты проверил, что он самый эффективный ? Ты скажешь наконец, что ты брал в качестве затрат и какой у тебя эффект, что бы можно было проверить это руками ?
I>>Linq это действительно прорыв. Главное не путать linq c query comprehension.
_>Ну разве что для людей считающих SQL идеалом DSL'ей для работы с коллекциями. )))
linq он нужен НЕ для работы с коллекциями. Коллекции — побочный эффект. Основная его фишка в том, что все relational-like структуры данных можно обрабатывать одним кодом независимо от источника — разные БД, XML, поток событий, Dataset/DataTable и даже коллекции, если они хранят relational-like данные и тд.
Здравствуйте, vdimas, Вы писали:
V>>>Конечно не беру, если мы все еще об встроенном async. Ручками я тебе что хошь накручу, ес-но, благо интероп и ансейф дотнета в "шаговой доступности". I>>То есть, не согласен, но ручками можно накрутить что угодно ? Не входит ли в это что угодно "произвольная модель" или как ?
V>Входит, ес-но, но поддержка её ср-вами языка — нет.
И в С++, что характерно, точно так же — скажем те же короутины буста сделаны самым честным хаком.
I>>И это неправильно. В сигнатуре должно быть указание, как можно вызывать метод и чего от этого можно ожидать.
V>Да никак. Обычно вызывай и все. Это именно настоящее "выпрямление" кода. Легковесная многозадачность, где ВНУТРИ метода стоят хинты, когда переключать задачу, как в виндах 3.x.
Ну ка, подробнее, что же за фокус такой, ты ни много ни мало утверждаешь, функция вдруг сама узнает, ожидаю ли я её результат и в зависимости от этого решит как делать процессинг ?
V>С т.з. вызывающего метода это обычный синхронный код, а вся асинхронность сугубо внешняя, как внешим является переключение потоков ОС по отношению к обычному коду на C#.
То есть, все функции будут синхронными с т.з. вызывающего кода, что внезапно останавливает message pump.
V>>>В том-то и дело, что под дотнетный async надо было разработать еще один фреймворк, помимо имеющегося под обычные коллекции, Rx или Linq + связку с этими имеющимися I>>А как ты хотел, что бы появились плюшки в языке и фремворки внезапно стали их поддерживать ?
V>Да. Программы для виндов 3.х прекрасно работали на win95, но уже с нормальной многозадачностью.
Не понял идею. Речь про изменения в языке и использование этих изменений во фремворках. Или винда вдруг стала каким то языком ?
V>Кишки могут торчать только в контрактах. А на уровне методов они должны быть. Конкретно тут кишки неблокирующей операции, но по этой строчке ничего нельзя сказать о коде. Асинхронность — это лишь название модели. Асинхронность может присутствовать и без поддержки языка.
см "функция вдруг сама узнает, ожидаю ли я её результат"
I>>Ну да, а у меня, прикинь, никакого async не торчит, вот незадача то.
V>Торчит в том месте, где надо требует контракт. Давай полные сигнатуры и мы проверим, подходят ли типы.
Pipeline pipe(Pipeline p)
V>Дык, async еще более не нужен хотя бы потому, что на порядки менее удобный.
"функция вдруг сама узнает, ожидаю ли я её результат"
I>>"якобы". О том, что это якобы как раз и должна сообщать сигнатура.
V>Не должна. Просто так сделано в конкретном языке. Но это было не обязательно.
"функция вдруг сама узнает, ожидаю ли я её результат"
V>Насколько я понял, там потом показали обертку над стандартной ф-ий с неблокирующими ветками.
Там были блокирующие вызовы.
I>>Вообще говоря искали альтернативы С++, потому резонно возник вопрос про асинхронщину.
V>Но с ней в С++ всегда было лучше, чем в других ООП языках, именно из-за многообразия функциональных типов и именно из-за того, что вся асинхронщина, которая "в лоб" (без asyc), идет как IoC, в котором функциональный подход заруливает ООП. А с короутинами еще проще...
Надо понимать async/await появились как ответ на одскульную асинхронщину.
Здравствуйте, Ikemefula, Вы писали:
I>Мне интересно, как ты проверил, что он самый эффективный ? Ты скажешь наконец, что ты брал в качестве затрат и какой у тебя эффект, что бы можно было проверить это руками ?
Нуу смотри. Предположим что у нас есть функция, которая делает какую-то полезную работу. Далее, у нас есть один вариант кода, который просто берёт и вызывает её. И есть второй вариант кода, который делает 20 вложенных вызовов функций-обёрток (причём не в исходнике, где это ещё может компенсировать компилятор, а в бинарнике), в самом низу которых и лежит наша полезная. Как ты считаешь, при таком раскладе я могу сказать, что первый вариант более эффективный чем второй, или же мне надо ещё пойти и поизмерять всё точно? )))
I>linq он нужен НЕ для работы с коллекциями. Коллекции — побочный эффект. Основная его фишка в том, что все relational-like структуры данных можно обрабатывать одним кодом независимо от источника — разные БД, XML, поток событий, Dataset/DataTable и даже коллекции, если они хранят relational-like данные и тд.
Под коллекциями я и подразумевал наборы данных, а не какие-то конкретные классы из C#. ) Только вот это не отменяет того, что набор команд SQL'я скажем так далеко не самый удобный.
Здравствуйте, Ikemefula, Вы писали:
I>await это не короутины, это поддержка асинхронных вычислений. Короутины просто используются для этого.
Гы, наоборот, Это просто ср-во реализации короутин.
Без проблем использовать await без всякой надуманной асинхронщины по прямому назначению — для того, чтобы наплодить легковесных безстековых короутин для той самой кооперативной многозадачности.
I>Ты путаешь два разных инструмента.
Еще раз. Асинхронность не требует короутин. Т.е. асинхронность не требует ни async в C#, ни короутины из буста или еще какой либы. Короутинам, в свою очередь, плевать на то, как называется код, который их использует. Это независимые трюки. Прибили их гвоздями друг к другу только в C#. Но и то, прибили не очень сильно, а только для невнимательных. Ты ведь можешь крутить почти такую же точно кооперативную многозадачность на своих async, обвинениями в которой ты уже прямо закидал короутины из буста. Почему почти такую же — потому что менее эффективную при вложенных вызовах и при разыменовании переменных в цепочке контекстов/замыканий из кучи при их вложенности. Ну и торчащие ослиные уши в сигнатурах доставляют.
Ну и названия ключевых слов вводят тебя в заблуждение настолько, что такое заблуждение преодолеть фактически нереально. )))
I>Предлагаешь обсудить твои фантазии ? Где ты видел высказыавния про великий прорыв, не имеющий аналогов и тд и тд ?
Ну так ты хвалишь заведомо более слабый инструмент, обвиняя более сильный в том, что это "просто кооперативная многозадачность". На C# async/await можно сэмулировать почти такую же. Только хуже. )))
Здравствуйте, vdimas, Вы писали:
I>>await это не короутины, это поддержка асинхронных вычислений. Короутины просто используются для этого.
V>Гы, наоборот, Это просто ср-во реализации короутин.
Это именно поддержка асинхронщины, т.к. короутины есть и без этого.
V>Без проблем использовать await без всякой надуманной асинхронщины по прямому назначению — для того, чтобы наплодить легковесных безстековых короутин для той самой кооперативной многозадачности.
Можно и это неосновное назначение.
V>Еще раз. Асинхронность не требует короутин.
Спасибо, капитан, я об этого говорил уже раз пятнадцать.
>Т.е. асинхронность не требует ни async в C#, ни короутины из буста или еще какой либы. Короутинам, в свою очередь, плевать на то, как называется код, который их использует. Это независимые трюки.
Ты и дальше будешь меня цитировать ?
V>Ну и названия ключевых слов вводят тебя в заблуждение настолько, что такое заблуждение преодолеть фактически нереально. )))
Я собтсвенно говорил про разницу между двумя вещами.
V>Ну так ты хвалишь заведомо более слабый инструмент, обвиняя более сильный в том, что это "просто кооперативная многозадачность". На C# async/await можно сэмулировать почти такую же. Только хуже. )))
Кооперативная многозадачность в чистом виде нужна чуть менее чем никогда.
Здравствуйте, alex_public, Вы писали:
I>>Мне интересно, как ты проверил, что он самый эффективный ? Ты скажешь наконец, что ты брал в качестве затрат и какой у тебя эффект, что бы можно было проверить это руками ?
_>Нуу смотри. Предположим что у нас есть функция, которая делает какую-то полезную работу. Далее, у нас есть один вариант кода, который просто берёт и вызывает её. И есть второй вариант кода, который делает 20 вложенных вызовов функций-обёрток (причём не в исходнике, где это ещё может компенсировать компилятор, а в бинарнике), в самом низу которых и лежит наша полезная. Как ты считаешь, при таком раскладе я могу сказать, что первый вариант более эффективный чем второй, или же мне надо ещё пойти и поизмерять всё точно? )))
То есть, эффективность меряем в символах кода ? Если так, то очевидно, что вариант с C# наиболее эффективный благодаря поддержке компилятора.
I>>linq он нужен НЕ для работы с коллекциями. Коллекции — побочный эффект. Основная его фишка в том, что все relational-like структуры данных можно обрабатывать одним кодом независимо от источника — разные БД, XML, поток событий, Dataset/DataTable и даже коллекции, если они хранят relational-like данные и тд.
_>Под коллекциями я и подразумевал наборы данных, а не какие-то конкретные классы из C#. ) Только вот это не отменяет того, что набор команд SQL'я скажем так далеко не самый удобный.
Для каких операций он не самый удобный ? для relational-like он практически самое лучше из того, что есть. ДЛя noSql он естесвенно не будет таким удобным, скажем для graph database нужна поддержка математики навроде bfs, dfs и тд.
Ты ошибочно понимаешь linq как мега универсальный подход. Он нужен для relational-like операций, данных и тд.
Здравствуйте, Ikemefula, Вы писали:
_>>По эффективности: у C# реализации будет O(N) по стеку, вместо O(1) I>Это копейки, потому что в асинхронщине основные издержки на порядки больше.
С какой радости?
Если у тебя десяток тыщ серверных соединений, то диспетчеризация — это фактически основные издержки.
I>Кривая архитектура, это когда переходы непойми где делаются. А когда код легко майнтейнить, это хорошая архитектура. async упрощает майнтенанс.
Ну ты же как-то поддерживаешь обычный код? Тебя же не смущает, что переключение потоков в многопоточной ОС происходит "где-то" за пределами твоей программы? Тут аналогично.
Здравствуйте, Ikemefula, Вы писали:
I>То есть, эффективность меряем в символах кода ? Если так, то очевидно, что вариант с C# наиболее эффективный благодаря поддержке компилятора.
Я же вроде там чётко написал что "не в исходнике". Так что речь грубо говоря о количестве процессорных инструкций затраченных на достижение одной и той же цели.
I>Для каких операций он не самый удобный ? для relational-like он практически самое лучше из того, что есть. ДЛя noSql он естесвенно не будет таким удобным, скажем для graph database нужна поддержка математики навроде bfs, dfs и тд. I>Ты ошибочно понимаешь linq как мега универсальный подход. Он нужен для relational-like операций, данных и тд.
Нуу про нетабличные данные то я вообще молчу. ))) Но и для табличных "самое лучше что есть" звучит очень забавно, особенно с учётом того, что SQL создавался не для программистов.
Здравствуйте, vdimas, Вы писали:
_>>>По эффективности: у C# реализации будет O(N) по стеку, вместо O(1) I>>Это копейки, потому что в асинхронщине основные издержки на порядки больше.
V>С какой радости? V>Если у тебя десяток тыщ серверных соединений, то диспетчеризация — это фактически основные издержки.
:faceplam:
Обработка IO completion уже займет порядка на три-четыре больше затрат. Для сравнения, один поток в nginx обрабатывает всего 1024 соединения. Ядро современного процессора делает делает примерно 5млрд операций в секунду. Обслуживание на async-await займет в худшем случае 1000-2000 тактов процессора. Это вообще ни о чем. Потому даже если С++ версия будет отрабатывать за 1 такт, то экономии нет и быть не может.
I>>Кривая архитектура, это когда переходы непойми где делаются. А когда код легко майнтейнить, это хорошая архитектура. async упрощает майнтенанс. V>Ну ты же как-то поддерживаешь обычный код? Тебя же не смущает, что переключение потоков в многопоточной ОС происходит "где-то" за пределами твоей программы? Тут аналогично.
Да вот как то смущает ибо надо использовать всевозможные схемы синхронизации. А теперь ты хочешь получить на ровном месте еще одну такую же по сложности проблему.