В языке Rust есть интересная фича: кооперативная многозадачность, реализованная в форме async/await и future. Интересно, можно ли на её основе сбацать простой симулятор цифровой логики. Когда-то я сделал такое на простом Си ("Симулятор RTL - это очень просто"). Но в Си пришлось задействовать setjmp/longjmp для переключение потоков, а тут вроде всё нужное прямо в языке дано.
Имеется хорошая статья, объясняющая подробности кооперативной многозадачности в Русте: https://os.phil-opp.com/async-await/
Имеется хорошая статья, объясняющая подробности кооперативной многозадачности в Русте: https://os.phil-opp.com/async-await/

no subject
Date: 2021-04-16 01:25 (UTC)no subject
Date: 2021-04-16 05:40 (UTC)Ведь когда мы ждём I/O, у нас OS сама отбирает timeslices by preemptive multitasking, причём именно в тот самый момент, когда мы делаем await в high-level language. А если не ждём I/O, то и отдавать нам добровольно нечего (а OS отбирает всё равно :).
Остаётся, конечно, экономия на деталях имплементации - в сервере нужно меньше managed threads, в GUI мы не блокируем UI, но как общая идея это как-то мелковато.
Кооперативная многозадачность была в 16-битных Windows, и как-то сразу было понятно, что так жить нельзя.
no subject
Date: 2021-04-16 05:58 (UTC)Это заметно, если по умолчанию выделять под стек каждому Thread по 4 MB.
В то же время в Windows можно экономно делать стек 128 KB. И так вместить много тысяч тредов.
no subject
Date: 2021-04-16 06:42 (UTC)no subject
Date: 2021-04-16 07:30 (UTC)С кооперативной многозадачностью можно писать без конкурентного доступа к данным.
no subject
Date: 2021-04-16 08:12 (UTC)no subject
Date: 2021-04-16 10:02 (UTC)А например в JavaScript всё в одном Thread, а албтернатива async/await - только цепочки континуаций.
no subject
Date: 2021-04-16 16:52 (UTC)А для С# и, видимо, Rust, кооперативные await/async никак не влияют на возможные способы синхронизации, так как не отменяют существующей preemptive, которая никуда не девается (ну, imho).
Тут, конечно, хорошо бы пример проекта, который перевели на await/async, и "всё прямо стало лучше", или "ничего не изменилось", но у меня такого нет. У меня все проекты с самого начала - или "threads по старинке", или "await/async".
no subject
Date: 2021-04-16 18:45 (UTC)Думаю, это один из немногих оправданных случаев, потому что параллельных запросов может быть очень много.
На десктоп приложениях я бы не связывался с async, польза не перевешивает сложности.
Есть известная статья про асинхронщину в виде метафоры красных и синих функций
https://habr.com/ru/post/466337/
no subject
Date: 2021-04-16 19:16 (UTC)Это была не главная поисковая страница Гугла, так что у меня не было тысячи запросов в секунду, но десятки были легко.
Честно говоря, никакой разницы в performance я не заметил. Вот и любопытно, обнаружил ли эту разницу кто-нибудь...
no subject
Date: 2021-04-16 21:01 (UTC)Маловероятно что кто-то поддерживает так 2 ветки.
Я полагаю, производительность не сильно отличается в нормальном режиме,
Но когда появляются запросы которые подвисли, например по причине ожидания внешних сервисов, то в варианте с Thread Pool начнется голодание
no subject
Date: 2021-04-17 07:18 (UTC)no subject
Date: 2021-04-16 06:20 (UTC)no subject
Date: 2021-04-16 06:38 (UTC)Исчезает привычный Stack Trace, вместо этого видно произвольный набор методов, которые завершились и как continuation вызвали другой Future и так по цепочке...
no subject
Date: 2021-04-17 07:07 (UTC)Тут есть два дополнительных момента:
1. Хоть C++ные, хоть Растовые сопрограммы опираюся на подсовываемую им библиотеку фьючеров, поэтому проблема отслеживания таких псевдостеков падает на эти библиотеки. Плюс отладчик. Но они все этого не умеют отслеживать.
2. Есть ситуации, когда отображение идет не напрямую 1:1, а N:1. Если реализоввать это в лоб, то оно делается циклом, и тогда первый фьючер попадает в цепочку, а остальные - нет, и неочевидно, к какому месту они прицепляются. Аналогично существуют и другие ситуации, когда фьючер не сразу соединяется с ожидающим его кодом, а заныкивается до лучших времен (другой типовой пример - пуб буферов фиксированного размера и ожидание пустого буфера когда они все заняты).
no subject
Date: 2021-04-17 15:49 (UTC)no subject
Date: 2021-04-16 06:52 (UTC)async/await - совсем не бесплатный механизм, для него нужно сохранение состояния треда. Его абьюз - это как сумму чисел в массиве считать, разбив массив на кусочки и дав по кусочку разным тредам: в реальных ситуациях вместо одного core будут заняты все, при этом latency упадёт на порядок, lose-lose situation.
no subject
Date: 2021-04-16 06:03 (UTC)Похоже современные языки сходятся к идентичной функциональности, различаясь только в синтаксисе.
Примерно как было со структурным программированием в 70-х.
no subject
Date: 2021-04-16 06:23 (UTC)no subject
Date: 2021-04-16 06:29 (UTC)https://en.cppreference.com/w/cpp/language/coroutines#co_await