Re: Вопрос по корутинам
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 27.08.25 12:45
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>А в каких задачах корутины вот прям супер — супер?

LVV>Чего раньше приходилось делать муторно и долго ?

Внутри async/await лежит тот же yield это энумераторы.
https://learn.microsoft.com/ru-ru/dotnet/csharp/asynchronous-programming/task-asynchronous-programming-model

Прелесть энумератора в том, что при вычеслении цепочки по MoveNext вычисление идет справа на лево. То есть обход начальной коллекции будет только 1 раз
и солнце б утром не вставало, когда бы не было меня
Отредактировано 27.08.2025 12:48 Serginio1 . Предыдущая версия .
Re: Вопрос по корутинам
От: ksandro Мухосранск  
Дата: 27.08.25 13:52
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>А в каких задачах корутины вот прям супер — супер?

LVV>Чего раньше приходилось делать муторно и долго ?


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

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

В первую очередь, где явно видно это преимущество, это работа с сетью. Например, у нас есть некий сервер, на который приходит запрос, получив этот запрос, чтобы обработать запрос, мы должны отправить еще несколько запросов, в разные базы данных которые крутятся на других серверах, и сформировать итоговый ответ, по результатам того, что пришло из баз. Корутина позволяет сделать это красиво и не плодить потоки.
Re: Вопрос по корутинам
От: novitk США  
Дата: 27.08.25 15:35
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>А в каких задачах корутины вот прям супер — супер?

LVV>Чего раньше приходилось делать муторно и долго ?

Генераторы в питоне для создания итераторов сильно проще чем интерфейс руками писать, нет?
Тут народ про async/await, но там корутины с concurrency смешаны и увидеть их сложнее.
Отредактировано 27.08.2025 18:23 novitk . Предыдущая версия . Еще …
Отредактировано 27.08.2025 15:40 novitk . Предыдущая версия .
Re[2]: Вопрос по корутинам
От: qqqqq  
Дата: 27.08.25 17:33
Оценка:
Здравствуйте, ksandro, Вы писали:
K>Корутины, это синтаксический сахар, позволяющий написать код, красивоо и линейно, вместо того, чтобы использовать коллбеки и постоянно передовать между ними контекст.

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


Как здесь может помочь корутина, то есть функция, которая может сама возвратиться из середины всли ей надо, но потом продолжить с этого места по сигналу?

Возможно корутина отправляет запрос на базу данных зависает в ожидании ответа? То есть несколько корутин для нескольких БД вызваны по очереди и ждут....
И судя по всему все ответы получает таки основной серверный поток, в нем типа еще один мини сервер который ждет ответы. Если что приходит, то главный поток анализирует откуда пришло и бУдит нужную корутину, передав ей видимо как-то этот ответ БД для обработки? А тогда корутина обрабатывает ответ и что то там генерит на основе его. А главный поток должен сообразить когда все корутины завершились или там после таймаута, выключить свой минисервер для БД, создать итоговый ответ для клиента "некого сервера".


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

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

Но и скорость обработки скорее всего у корутин ниже. Потоки могут одновременно работать а корутины это просто функции. Если одна работает то все остальные созданные основным потоком да и сам основной поток ничего не делают, ждут когда корутина вернет управление.
Re[3]: Вопрос по корутинам
От: ksandro Мухосранск  
Дата: 27.08.25 19:00
Оценка:
Здравствуйте, qqqqq, Вы писали:

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

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

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


Q>Как здесь может помочь корутина, то есть функция, которая может сама возвратиться из середины всли ей надо, но потом продолжить с этого места по сигналу?


Q>Возможно корутина отправляет запрос на базу данных зависает в ожидании ответа? То есть несколько корутин для нескольких БД вызваны по очереди и ждут....

Q>И судя по всему все ответы получает таки основной серверный поток, в нем типа еще один мини сервер который ждет ответы. Если что приходит, то главный поток анализирует откуда пришло и бУдит нужную корутину, передав ей видимо как-то этот ответ БД для обработки? А тогда корутина обрабатывает ответ и что то там генерит на основе его. А главный поток должен сообразить когда все корутины завершились или там после таймаута, выключить свой минисервер для БД, создать итоговый ответ для клиента "некого сервера".


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


Q>В чем корутины лучше то? Потоков не создается, так это не проблема в общем в настоящее время. Конечно если запросов ну очень много надо это как-то регулировать.


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



ИМХО Вы не очень хорошо понимаете сути ассинхронности, принципы работы сети и неблокирующих вызовов.

Есть высоконагруженный сервер. К нему каждую секунду поступает 100500 запросов. Если на каждый запрос создавать поток, а затем еще создавать поток для запроса к БД, то сервер будет тратить большую часть ресурсов исключительно на создание/убийство потоков, а так же на их синхронизацию, при этом потоки большую часть времени будут ничего не делать а просто спать ожидая ответа от бд, в итоге мы имеем очень низкую производительность трату огромных ресурсов на ничего не делание. Поэтому уже давно высокопроизводительные сервера работают несколько подругому. На самом деле с сетью работает ядро, да и с дисками работает ядро, и есть специальные системные вызовы, сигнализирующие нам о том, что какой-то в какой-то файл/сокет доступен для чтения/записи (epoll, IOCP). Да нам нужно что-то типа планировщика. В обычной ситуации мы сохраняем контекст запроса, затем можем ожидать или отправлять следующие запросы. Когда пришел ответ, мы вызываем некий коллбэк. Корутина отправляет запрос и возвращается, когда приходит ответ мы в качестве коллбека вызываем ту же самую корутину, и она продолжает работату с того самого места, где мы отправили запрос. То есть внутри корутины все выглядит как синхронная процедура, после запроса мы получаем ответ, и продолжаем работу.
Описал я как-то сумбурно, но вообще это сложно объяснить в двух словах. посмотрите например на примеры работы библиотеки boost asio (https://www.boost.org/doc/libs/latest/doc/html/boost_asio/examples/cpp20_examples.html#boost_asio.examples.cpp20_examples.coroutines) код с корутинами выглядит красивее. Ну и вообще погуглите про написание сетевых программ на базе корутин. Код с корутинами по скорости работает так же как неблокирующий сервер на коллбеках, накладные расходы минимальны, не сравнить с порождением потока на каждый чих. Есть еще стекфул корутины и файберы, тоже интересная штука.
Re: Вопрос по корутинам
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 27.08.25 19:13
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>А в каких задачах корутины вот прям супер — супер?

LVV>Чего раньше приходилось делать муторно и долго ?

Фоновый процессинг,
Шедулинг всякий
Асинхронная обработка данных
Re[5]: Вопрос по корутинам
От: landerhigh Пират  
Дата: 27.08.25 21:09
Оценка:
Здравствуйте, rg45, Вы писали:

R>Офигенная машина состояний. Паровоз Черепановых нервно пыхтит в коридоре


Да. Стоит немного усложнить:

#include <generator>
#include <iostream>
#include <string>

std::generator<std::string> runMachine(int& param) {
    co_yield "Idle";
    co_yield "Started";
    co_yield "Processing";
    while (param < 10)
    {
        co_yield "Waiting";
    }
    co_yield "Stopped";
}

int main() {
    int iValue = 0;
    for (const std::string& state : runMachine(iValue))
    {
        ++iValue;
        std::cout << "State: " << state << std::endl;
    }
}


Вот так спагетти колбеков можно спокойно завернуть в корутину.
Вместо int& param вверху передается некий ServerInterface и вперед.
www.blinnov.com
Re[4]: Вопрос по корутинам
От: so5team https://stiffstream.com
Дата: 28.08.25 04:05
Оценка:
Здравствуйте, ksandro, Вы писали:

K>Описал я как-то сумбурно, но вообще это сложно объяснить в двух словах. посмотрите например на примеры работы библиотеки boost asio (https://www.boost.org/doc/libs/latest/doc/html/boost_asio/examples/cpp20_examples.html#boost_asio.examples.cpp20_examples.coroutines) код с корутинами выглядит красивее.


До тех пор пока в отладке не придется разбираться во что превращается каждый co_await, co_return и co_yield.

Из того, что вы описали про "преимущества" stackless-короутин складывается устойчивое ощущение, что все тоже самое было бы еще гораздо проще и удобнее со stackfull-короутинами. Где был бы линейный код без мусорных co_, аналогичный тому, чтобы написали бы "в лоб" на голых нитях, но без оверхэда этих самых голых нитей.
Re[6]: Вопрос по корутинам
От: kov_serg Россия  
Дата: 28.08.25 06:03
Оценка: :)
Здравствуйте, landerhigh, Вы писали:

L>Да. Стоит немного усложнить:


А теперь запустите 3 таких машины.
Re[7]: Вопрос по корутинам
От: rg45 СССР  
Дата: 28.08.25 06:17
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>А теперь запустите 3 таких машины.


Да не вопрос:

http://coliru.stacked-crooked.com/a/0b96eda764fa66eb

#include <generator>
#include <iostream>
#include <string>
#include <ranges>

std::generator<std::string> runMachine(const int& param) {
    co_yield "Idle";
    co_yield "Started";
    co_yield "Processing";
    while (param < 10)
    {
        co_yield "Waiting";
    }
    co_yield "Stopped";
}

int main() {
    int iValue = 0;
    for (const auto&[state1, state2, state3] : std::views::zip(runMachine(iValue), runMachine(iValue), runMachine(iValue)))
    {
        ++iValue;
        std::cout << "State1: " << state1 << ", State2: " << state2 << ", State3: " << state3 << std::endl;
    }
}

State1: Idle, State2: Idle, State3: Idle
State1: Started, State2: Started, State3: Started
State1: Processing, State2: Processing, State3: Processing
State1: Waiting, State2: Waiting, State3: Waiting
State1: Waiting, State2: Waiting, State3: Waiting
State1: Waiting, State2: Waiting, State3: Waiting
State1: Waiting, State2: Waiting, State3: Waiting
State1: Waiting, State2: Waiting, State3: Waiting
State1: Waiting, State2: Waiting, State3: Waiting
State1: Waiting, State2: Waiting, State3: Waiting
State1: Stopped, State2: Stopped, State3: Stopped

И чо?

Теперь асинхронность появилась?
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 28.08.2025 6:36 rg45 . Предыдущая версия . Еще …
Отредактировано 28.08.2025 6:21 rg45 . Предыдущая версия .
Отредактировано 28.08.2025 6:18 rg45 . Предыдущая версия .
Re[7]: Вопрос по корутинам
От: landerhigh Пират  
Дата: 28.08.25 06:40
Оценка:
Здравствуйте, kov_serg, Вы писали:

L>>Да. Стоит немного усложнить:

_>А теперь запустите 3 таких машины.

Да хоть 333.
В чем проблема?
www.blinnov.com
Re[8]: Вопрос по корутинам
От: kov_serg Россия  
Дата: 28.08.25 06:43
Оценка: :)
Здравствуйте, rg45, Вы писали:

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


_>>А теперь запустите 3 таких машины.


R>Да не вопрос:

R>И чо?

R>Теперь асинхронность появилась?


Теперь пусть одна из них постепенно создаст еще 2 асинхронных машины, что бы их было не больше 5 нет лучше 6 штук.
И каждая из них имеет разное кол-во итераций до окончания.
Re[8]: Вопрос по корутинам
От: kov_serg Россия  
Дата: 28.08.25 06:45
Оценка:
Здравствуйте, landerhigh, Вы писали:


L>Да хоть 333.

L>В чем проблема?
Хорошо запустите 333 таких машины. На код посмотреть. На эргономичноть, так сказать.
Re[9]: Вопрос по корутинам
От: rg45 СССР  
Дата: 28.08.25 06:50
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Теперь пусть одна из них постепенно создаст еще 2 асинхронных машины, что бы их было не больше 5 нет лучше 6 штук.

_>И каждая из них имеет разное кол-во итераций до окончания.

Ну вот тогда уже и появится асинхронность (я ж и не говорил, что это невозможно). Только эта асинхронность будет привнесена программистом, а не являться свойством самих корутин.
--
Справедливость выше закона. А человечность выше справедливости.
Re[5]: Вопрос по корутинам
От: landerhigh Пират  
Дата: 28.08.25 06:54
Оценка:
Здравствуйте, so5team, Вы писали:

S>До тех пор пока в отладке не придется разбираться во что превращается каждый co_await, co_return и co_yield.


И во что он превращается и, главное, зачем с этим нужно разбираться при, гхм, "отладке"?

S>Из того, что вы описали про "преимущества" stackless-короутин складывается устойчивое ощущение, что все тоже самое было бы еще гораздо проще и удобнее со stackfull-короутинами.


На то, что корутины из 20 стандарта бесстековые, тут пока никто внимание особо не обращал. И уж тем более никто не говорил про их преимущества и недостатки перед корутинами стековыми. Просто кое-кому просто захотелось поумничать

S>но без оверхэда этих самых голых нитей.


Оверхед на переключение контекста в случае стековых корутин примерно равен ему же для нитей (порядка 170 инструкций). Плюс память для стека. Удачи запустить 1000 корутин.
www.blinnov.com
Отредактировано 28.08.2025 7:02 landerhigh . Предыдущая версия .
Re[9]: Вопрос по корутинам
От: rg45 СССР  
Дата: 28.08.25 06:55
Оценка: +1
Здравствуйте, kov_serg, Вы писали:

_>Хорошо запустите 333 таких машины. На код посмотреть. На эргономичноть, так сказать.


Так нужно же с чем-то сравнивать. Чего просто так смотреть.
--
Справедливость выше закона. А человечность выше справедливости.
Re[10]: Вопрос по корутинам
От: kov_serg Россия  
Дата: 28.08.25 06:58
Оценка:
Здравствуйте, rg45, Вы писали:


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

Так асинхронность важна не сама по себе. Её должно быть удобно использовать. Корутины сами по себе не есть асинхронность, просто запись кода.
Асинхронность это правила и гарантии которые этому коду позволят правильно работать.
Re[11]: Вопрос по корутинам
От: rg45 СССР  
Дата: 28.08.25 07:03
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Так асинхронность важна не сама по себе. Её должно быть удобно использовать. Корутины сами по себе не есть асинхронность, просто запись кода.

_>Асинхронность это правила и гарантии которые этому коду позволят правильно работать.

Все эти высказывания не вызывают возражений.

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

Ты не мог бы сформулировать тезис, который ты доказываешь?
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 28.08.2025 7:04 rg45 . Предыдущая версия .
Re[6]: Вопрос по корутинам
От: so5team https://stiffstream.com
Дата: 28.08.25 07:04
Оценка:
Здравствуйте, landerhigh, Вы писали:

S>>До тех пор пока в отладке не придется разбираться во что превращается каждый co_await, co_return и co_yield.


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


В обычную нечитаемую лапшу, надо полагать.

S>>Из того, что вы описали про "преимущества" stackless-короутин складывается устойчивое ощущение, что все тоже самое было бы еще гораздо проще и удобнее со stackfull-короутинами.


L>На то, что корутины из 20 стандарта безстековые, тут пока никто внимание особо не обращал.


Поскольку в C++ короутины только безстековые, то разговаривать можно было только о них.

L>Просто кое-кому просто захотелось поумничать


Кого-то просили привести пример преимущества короутин над КА, но кто-то что-то проигнорировал.

S>>но без оверхэда этих самых голых нитей.


L>Оверхед на переключение контекста в случае стековых корутин примерно равен ему же для нитей (порядка 170 инструкций). Плюс память для стека. Удачи запустить 1000 корутин.


ЕМНИП, яндексовский userver с этой задачей спокойно справляется.
Re[12]: Вопрос по корутинам
От: kov_serg Россия  
Дата: 28.08.25 07:22
Оценка:
Здравствуйте, rg45, Вы писали:

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


R>Ты не мог бы сформулировать тезис, который ты доказываешь?

Сами по себе коротиные не решают пробелему асинхронного исполнения, она немного в другой плоскости и не связана с корутинами.
Корутины это просто сопособ записи. Без них можно спокойно писать точно такой же код. При этом достаточно обычного голого C.
Главная засада в планировщие он диктует все правила и гарантии для асинхронного кода.
Например в самом простом случае: real-time коде это обязательство вызывать асинхронный код регулярно (например 1000 раз в сек), а сам код дожен успевать испольнятся (менее чем за 1мс).
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.