Apr. 10th, 2020

elglin: (Default)
В замечательном, пусть и не особо распиаренном фильме The Prestige есть следующий абсолютно замечательный диалог:
- Mr. Angier, have you considered the cost of such a machine?
- Price is not an object.
- Perhaps not, but have you considered the cost?
Причем Боуи в роли Теслы это "cost" произносит так, что выделение физически ощутимо.
Вот и мне интересно, хорошо ли подумали те, кто был должен, о стоимости всего текущего карантина. Потому что вирус приходит и уходит, а кушать хочется всегда.
elglin: (Default)
Продолжаю мучать asyncio и, ознакомившись с асинхронщиной, как она есть в C#, задумался.
В Boost::asio (да, это плюсы), когда ты "вызываешь" бесстековую корутину, ты передаешь ей управление. Дальше она может передать его куда-то еще и так далее, потом это вернется в event loop.
В решетке, судя по всему, равно как и в node.js, происходит именно то же самое. Это позволяет реализовать полезную последовательность действий:
1) Запустить вызов, который вернет хз когда (допустим, REST-запрос к задумчивой апишке), но быстро сядет ждать ввода-вывода и вернет управление в event loop
2) Эвентуально получить управление у event loop и делать полезные дела
3) Когда совсем невмоготу жить без ответа, сказать await.
В Python-asyncio все интереснее. Что бы ты ни сказал, create_task(), call_soon() и так далее, ты не отдал управление. То есть вот этот твой длинный и задумчивый вызов не начнет работать, пока ты не скажешь await (необязательно await этого вызова). На большом потоке запросов и фиг бы с ним, но даже на малом все будет тормоз-з-зить. А слова yield нет, выкинули его, как только отвязали asyncio от генераторов.
В гугле набрел на гитхаб и на комменты не кого-нибудь, а лично Гвидо ван Россума. Короче, решение такое (хак, но прикольно):
task = asyncio.create_task(very_long_running_coro())
await asyncio.sleep(0) # HACK relinquishes control to event loop, should have minimal overhead
...
# do stuff
...
await task

Конечно, здесь ты не передаешь прямо управление в корутину, а отдаешь в event loop, но если верить документации (не тестил), то корутина, отданная create_task(), исполнится первой после возвращения управления в event loop. Если нужна прямо-таки гарантия, то надо юзать call_soon(), там прямым текстом сказано, что позовут первым делом после возврата управления в event loop.

Причем в тех же комментах поминается про некий пулл, после которого asyncio.sleep(0) специально офигенно быстр, чтобы работать заменой yield.
Page generated Jun. 30th, 2025 10:37 pm
Powered by Dreamwidth Studios