Comments 13
При переключении задач процессору же нужно данные от предыдущей задачи сохранить. А перед этим понять в каких регистрах задача данные хранит и их где-то сохранить? Правильно? Где оно сохраняется и как это происходит? Ведь по факту это тоже самое переключение контекста только в миниатрюре.
Первое зависит от реализации. Платформа, предоставляющая event loop и асинхронное API действительно может создать сколько угодно других потоков и просто перекидывать данные оттуда в «наш главный». Но по факту новые потоки нужны только если что-то действительно вычисляем, опросить состояние IO (пример с БД) можно и в том же самом. А как там ОС это проворачивает — неизвестно, может у неё отдельный поток тоже для всего IO, я не знаю.
Второе: да, то же самое микропереключение. Только всё состояние живёт в замыканиях функций. Что, по сути, ничем не отличается от поточного контекста. Т.е. если бы мы это делали там, где нет замыканий, нам пришлось бы в функции, запрашивающие старта асинхронной операции, передавать не только коллбэк, но и какой-то объект контекста, который будет передан этому обработчику во время его вызова.
Тут важно ещё понимать, что «обращение к БД» в основном… не происходит, мы почти всё время просто ждём. Записать/прочитать данные в буффер и отправить его сетевой карте — это относительно быстрая операция, относительно времени, которое проходит между такими операциями. И если у нас времени ожидания достаточно, чтобы ещё повычислять чего-нибудь другого — нам не нужен ещё один поток.
Базовая "фоновая" IO-операция, такая как чтение или запись в сокет либо в файл, фонового потока не требует*
. Она выполняется с использованием неблокироющего сокета или асинхронного API.
Более сложные фоновые задачи зависят от того, кто и как их писал. Если это внешняя библиотека (например, тот же драйвер БД) — то вполне возможно, что она будет использовать блокирующие операции, а значит вызовы надо выносить в отдельный пул потоков.
Если же задача была написана с использованием асинхронных операций — то нет никаких причин существовать дополнительному фоновому потоку во время выполнения задачи.
*
говорят, в linux есть проблемы с файловым асинхронным вводом-выводом, из-за чего в некоторых конфигурациях серверу nginx приходится "выталкивать" чтение файлов в пул потоков. Но сетевой ввод-вывод, а именно он создает больше всего задержек, заставить работать полностью асинхронно не так и трудно.
Разработчики Python просто клепают библы на C++ к.е. запускают поток параллельный главному и перекидывают таски туда.
Но, в итоге, все равно же получается очередь сообщений между потоками, этакая микро- RabbitMQ
Она про async/await из C#, но, думаю, принципиальной разницы тут нет.
try { let a = await something(); let b = await xxxxx(a); // или еще что угодно - хоть последовательно, хоть параллельно } catch (e) { console.log(e); throw e; // или еще что-нибудь }
Вот это можно запихнуть в async-функцию, и оно будет работать, как ожидается. И стектрейс будет внятным!
Async-await возвращают исключения в JS, с которыми у него было туго с момента самого появления. (А также возвращают исключения в асинхронное программирование в любом другом языке.)
Внятные стектрейсы зависят только от используемой реализации обещаний (Promise). Ключевые слова async и await тут ни при чем. Нативные обещания в том же Chrome — да, дают внятные стектрейсы (в других браузерах не проверял). А вот всяческие полифилы могут и порушить все.
Написал «а внутрь неё подаётся получившееся R, либо возбуждается исключение E», но не уточнил, что исключение прямо внутри корутины возникает, ну и примера нет, спасибо.
Нет, асинхронность может существовать там, где нет никакого event loop'а. Ведь ничто не мешает передать в любой поток коллбэк, который будет вызван, как что-нибудь произошло.
Кооперативная многозадачность решённая через event loop просто порождает асинхронность, а не является ей. Асинхронность — просто абстрактное понятие, описывающее процессы, которые происходят не мгновенно.
А это случайно не заблуждение отождествлять асинхронизм в глобальном его понимании с конкурентностью? На некоторых платформах(типа jvm) асинхорнизм построен на многопоточности ибо по другому там никак, но это всего лишь частный случай. Если брать ко-рутины то они там совсем по другому построены, и конкурентность там не причем.
Конкурентность: Асинхронность