Re[3]: Асинхронщина
От: landerhigh Пират  
Дата: 06.12.25 13:29
Оценка: +1
Здравствуйте, Videoman, Вы писали:

N>>Если посмотреть на userver, который делает всё то, что тебе надо, то видно, что он C++17 требует. То есть его достаточно.


V>Мне показалось, что там во всю стекфул корутины используются. Подход понятен, но мне хотелось бы получить что-то в стиле node.js. Один основной поток, в котором логика строго однопоточная, без необходимости синхронизации. Мне показалось, что со стекфул корутинами, если мы используем сразу кучу ядер,


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

V>Уточню. У меня задача не запускать паралльно несколько независимых веток исполнения, а делать все по очереди (псевдопараллельно(, как будто в одном потоке, без синхронизации. Если на низком уровне рассматривать, похоже на большой автомат, но который каждый цикл выполняет одну и ту же логику, но она огромная размазана между кучи ожиданий IO, иногда вложенных. Похоже на то, как работает node.js. Ощущение, что безстековые корутины тут лучше подходят или я не прав?


Тут подходят безстековые корутины. И стековые тоже подходят.
Разница между ними в том, что в случае безстековых корутин сохранение контекста либо делается вручную, либо должно поддерживаться языком/средой (в случае 20х корутин это делает компилятор, как правило выделяя память на куче). Для стековых корутин должен выделяться отдельный стек, и запуск/выход из них связан с необходимостью сохранения и восстановления всех регистров, что относительно дорого. Из плюсов стековых корутин можно назвать то, что переключение контекста возможно из любой функции в стеке вызовов, при этом функции выше по стеку вообще могут не знать, что они выполняются в контексте корутины.
Re: Асинхронщина
От: AleksandrN Россия  
Дата: 06.12.25 18:47
Оценка:
Здравствуйте, Videoman, Вы писали:

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


Для ожидания события в сокете можно использовать poll/epoll/select/kqueue (сокет должен быть не блокируемым). Но кросс-платформенный из этого только select.
В кроссплатформенных библиотеках boost::asio, libevent и ещё нескольких именно эти механизмы и используются.

Можно коллбек прикрутить, можно в отдельном потоке ответ ждать, причём можно ждать ответ более, чем на одном сокете.
Re: Асинхронщина
От: Pitirimov США  
Дата: 07.12.25 22:37
Оценка:
Здравствуйте, Videoman, Вы писали:
V> ... кто как подходит к IO-bound задачам, где CPU, будем считать для простоты, почти не используется и в основном приходится ждать завершение операций.

Я бы просто запускал новый поток и ожидал сообщения от него о завершении обмена данными. Ядер у современных процессоров гораздо больше одного и в наши дни неразумно обрабатывать все задачи сопрограммами на одном ядре процессора вместо многопоточной, многоядерной обработки.
Re[2]: Асинхронщина
От: kov_serg Россия  
Дата: 08.12.25 07:28
Оценка:
Здравствуйте, Pitirimov, Вы писали:

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

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

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


Дык если потоков много очень большие накладные расходы по памяти и на переключение, да и кэш бодро вымывается.
Поэтому вместо миллиона тактов на переключения потока использоую сотни тактов на планировщик и вместа 4мб стека на поток мелкие стуктуры и coroutine-ы.
В результате выигрыш по производительности может быть очень ощутимым. Если бы он был не значительным миллионы мух не заморачивались бы.
Отредактировано 08.12.2025 7:29 kov_serg . Предыдущая версия .
Re[2]: Асинхронщина
От: so5team https://stiffstream.com
Дата: 08.12.25 07:33
Оценка:
Здравствуйте, Pitirimov, Вы писали:

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

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

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


Довелось лет 5 назад понаблюдать за тем, как Linux вставал колом на такой модели thread per connection когда количество одновременно обслуживаемых соединений превышало 32K штук.

Не надо так делать.
Re[2]: Асинхронщина
От: Videoman Россия https://hts.tv/
Дата: 08.12.25 18:52
Оценка:
Здравствуйте, Pitirimov, Вы писали:

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


В моих новых задачах мне такое не подходит. Говорю же CPU-bound. Основному потоку нечего желать, только логику распределять, всё на ожидании висит. Вот только автомат по логике получается безумный. Поэтому хочется всё это выпрямить. Зачем тут стрелять из пушки.
Re[4]: Асинхронщина
От: Videoman Россия https://hts.tv/
Дата: 08.12.25 19:13
Оценка:
Здравствуйте, landerhigh, Вы писали:

L>Именно что показалось.

L>Корутина — это не поток. Это просто возможность прервать выполнение функции и потом продолжить с того же места. Когда прервать и когда продолжить, решать программисту, т.е. тебе.

А я где-то написал что корутина это — поток . Корутина это не поток, но выполняется она не в вакуме, а в контексте потока ОС.

L>Тут подходят безстековые корутины. И стековые тоже подходят.

L>Разница между ними в том, что в случае безстековых корутин сохранение контекста либо делается вручную, либо должно поддерживаться языком/средой (в случае 20х корутин это делает компилятор, как правило выделяя память на куче). Для стековых корутин должен выделяться отдельный стек, и запуск/выход из них связан с необходимостью сохранения и восстановления всех регистров, что относительно дорого. Из плюсов стековых корутин можно назвать то, что переключение контекста возможно из любой функции в стеке вызовов, при этом функции выше по стеку вообще могут не знать, что они выполняются в контексте корутины.

Я знаю чем стековые корутины отличаются от безстековых, только вот разница большая, на мой взгляд. Как я понимаю, в случае стековых корутин мне придется всё равно писать в многопоточном стиле, пофигу что физически поток один, нити то разные и стеки тоже. Потом придется как-то контекст руками размазывать по нитям, делать аналог join. Отличий от потоков почти никакой, с той лишь разницей, что мы оптимизируем переключение контекста оптимизирую по CPU, а мне это не нужно, хотелось бы логику выпрямить.
Меня интересуют безстековые корутины или их заменители, когда вся логика в основном потоке. Еще большой плюс, что можно использовать пул потоков, в которых выполнять асинхронные операции изолированно, а результат возвращать основному потоку. Видимо придется использовать 20-й стандарт.

А на 20-м стандарте есть какие-нибудь библиотеки, которые использую корутины оттуда? Была бы идеальна обертка libuv в С++20 корутины, кажется.
Re[5]: Асинхронщина
От: so5team https://stiffstream.com
Дата: 09.12.25 05:51
Оценка:
Здравствуйте, Videoman, Вы писали:

V>А на 20-м стандарте есть какие-нибудь библиотеки, которые использую корутины оттуда? Была бы идеальна обертка libuv в С++20 корутины, кажется.


На Reddit-е на днях кто-то запостил ссылку на свою такую обертку: https://old.reddit.com/r/cpp/comments/1pep8ie/introducing_asyncio_a_new_opensource_c23/
Но она требует C++23.
Re: Асинхронщина
От: B0FEE664  
Дата: 09.12.25 13:59
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Что в идеале хочется получить:

V>
V>data = await read(...);
V>await write(data);
V>

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

std::future, std::async
И каждый день — без права на ошибку...
Re[2]: Асинхронщина
От: sergii.p  
Дата: 09.12.25 15:24
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>std::future, std::async


это же создаст сонм потоков-бездельников
Re[5]: Асинхронщина
От: Великий Мессия google
Дата: 09.12.25 17:41
Оценка:
V>А на 20-м стандарте есть какие-нибудь библиотеки, которые использую корутины оттуда? Была бы идеальна обертка libuv в С++20 корутины, кажется.

на гитхабе с десяток тех оберток вокруг libuv которые дают возможностью юзать co_await итд соцпрограммы из С++17+

но все же asio VS libuv
лучше asio
хотя некоторые плюсики и у в libuv есть
Re[3]: Асинхронщина
От: B0FEE664  
Дата: 09.12.25 18:51
Оценка:
Здравствуйте, sergii.p, Вы писали:

BFE>>std::future, std::async

SP>это же создаст сонм потоков-бездельников

Или не создаст.
Зависит от имплементации.
Имплементация может использовать thread pool.
Так как у меня задачи совсем не укладываются в описанный топикастером подход, то на практике я эти функции не использовал, но, теоретически, как мне кажется, связка future + async укладывается в описанную задачу, как я её понял.
И каждый день — без права на ошибку...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.