LINUX.ORG.RU

В чем польза asyncio?

 ,


0

4

Допустим у меня стоит задача опроса состояния GPIO-пина и выполнения некоторых действий в связи с этим.

Я могу поступить по-простому:

завернуть пару-тройку for-while циклов, сделать в них poll состояния и логику того, что делать если состояние изменилось.

А могу использовать asyncio. И я пока не понимаю, чем он отличается от такой же for-loops по большому счету, кроме того что представляет некоторую абстракцию над ними.

Ну то есть читаемость - да, улучшается.

А в плане производительности например, это будет бонус или наоборот? Если будет, то от чего?

★★★★★

тем что в первом случае ты городишь некое подобие event loop'а сам, а во втором случае используешь готовый, с кучей плюшек и синтаксического сахара

eternal_sorrow ★★★★★ ()

А в плане производительности например, это будет бонус или наоборот?

при использовании стандартного event loop'а из asyncio может и не будет прироста. или будет, но минимальный. но можно использовать uvloop, он очень быстрый

eternal_sorrow ★★★★★ ()
Ответ на: комментарий от eternal_sorrow

хотя нет, что это я. будет прирост даже со стандартным. засчёт асинхронности блокирующих операций. когда некая корутина делает await на операцию, которая блокирует поток выполнения этой корутины, например пишет в файл или взаимодействует с сетью, то event loop приостанавливает выполнение этой корутины и переключается на следующую, а когда блокирующая операция завершается, выполнение возобновляется. таким образом интерпретатор не простаивает в момент выполнения блокирующей операции.

eternal_sorrow ★★★★★ ()
Ответ на: комментарий от alpha

https://github.com/torvalds/linux/blob/master/include/uapi/linux/gpio.h#L115

GPIO_GET_LINEEVENT_IOCTL возвращает тебе файловый дескриптор, который уже надо поллить на предмет событий на этой линии

это нативная асинхронщина - или нет? :)

alpha ★★★★★ ()
Ответ на: комментарий от eternal_sorrow

Это не тру способ. Там в фоне отдельно висящий демон. И скорее всего тоже зависящий от того gpio-интерфейса который задепрекейтят в 2020.

alpha ★★★★★ ()
Последнее исправление: alpha (всего исправлений: 1)
Ответ на: комментарий от alpha

что значит «нативная асинхронщина»?

А как ещё назвать IO-операции, которые в парадигме корутин? На уровне самой asyncio по-моему только сокеты поддерживаются.

vvn_black ★★★★ ()
Ответ на: комментарий от pawnhearts

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

eternal_sorrow ★★★★★ ()
Ответ на: комментарий от shkolnick-kun

Мне шашечки конечно.

Ну то есть я в итоге хочу _правильную_ реализацию асинхронного gpio через /dev/gpiodev.

Я так понимаю что это должно получаться достаточно просто если использовать asyncio c https://docs.python.org/3/library/asyncio-eventloop.html#watching-file-descri...

а file descriptor я уже умею получать

alpha ★★★★★ ()
Ответ на: комментарий от alpha

asyncio просто аккуратно эти fd в epoll засунет. Гугл вроде говорит, что такие fd в epoll пихать можно, значит всё ок будет.

завернуть пару-тройку for-while циклов, сделать в них poll состояния и логику того

Это либо увеличит задержку обработки до периода твоего poll, либо нагрузит процессор мусорной нагрузкой и сожрёт батарейку.

snizovtsev ★★★ ()
Ответ на: комментарий от shkolnick-kun

подробности: https://stackoverflow.com/questions/49005651/how-does-asyncio-actually-work

Вроде то что надо, но очень много букв, потом ещё повнимательнее почитаю.

Получается что asyncio не использует потоки, всё выполняется в одном. Выигрыш просто за счёт продвинутой логики что именно ставить на паузу в данный момент.

При этом с I/O получается так что мы можем проверить готов ли сокет для чтения перед тем как пытаться его читать, и потому можем откладывать чтение, если сокет не готов.

Что меня всё время путает - это фразы такого типа

Select is a blocking function, implemented by the operating system underneath, that allows waiting on sockets for incoming or outgoing data. Upon data being received it wakes up, and returns the sockets which received data, or the sockets whom are ready for writing.

Socket is a ... function ... it wakes up

Если там один поток и что-то поставлено на паузу, то функция не может просыпаться. Это event loop должен в какой-то момент про неё вспомнить, придти, проверить какой-то флаг и её «проснуть». Так ведь?

alpha ★★★★★ ()
Последнее исправление: alpha (всего исправлений: 1)
Ответ на: комментарий от vvn_black

Да, как-то непонятно что имеется в виду.

То есть они говорят что monitor file descriptor for read availability и monitor file I/O - это совсем разные вещи.

Может monitor file i/o - это когда кто-то другой пишет/читает, а ты со стороны пытаешься определить что там происходит?

alpha ★★★★★ ()
Ответ на: комментарий от alpha

Если там один поток и что-то поставлено на паузу, то это что-то не может просыпаться. Это event loop должен в какой-то момент про неё вспомнить, придти, проверить какой-то флаг и её «проснуть». Так ведь?

man 2 select
man 7 epoll

asyncio синтаксический сахар над ними. Идея в том, что мы делаем read/write над обычными fd, но с флагом NONBLOCK - который гарантирует, что процесс не войдёт в Sleep state, а вернёт errno = WOULDBLOCK. Дальше если всё что мы хотим читать/писать вернуло WOULDBLOCK - вручную вызываем sleep state на сразу множество fd. После просыпания ядро гарантирует (почти), что один из fd можно читать-писать без блокировки (есть данные в буфере). asyncio это всё автоматизирует синтаксическим сахаром до уровня как будто бы мы используем несколько тредов.

snizovtsev ★★★ ()
Ответ на: комментарий от alpha

Там ивент лупы:

https://docs.python.org/3/library/asyncio-eventloops.html

которые работают поверх:

https://docs.python.org/3/library/selectors.html#module-selectors

у которых внутри select, poll, epoll, Kqueue...

shkolnick-kun ★★★ ()
Последнее исправление: shkolnick-kun (всего исправлений: 1)
Ответ на: комментарий от vvn_black

Что-то я не понял вот это

С точки зрения мультиплексора файл на диске всегда готов к чтению, не смотря на то что операция чтения может (и будет) блокировать на время чтения с носителя.

С записью примерно то же саме.

Это by design как говорится. Т.е юзать мультиплексоры на регуляр файлах можно, но смысла в этом нет.

redixin ★★★★ ()
Ответ на: комментарий от ggrn

что почитать чтобы закрыть пробелы в этой теме?

Почитать буквари по select poll epoll.

Не лишним будет почитать доки по виндовым асинхронным файловым апи чтобы понимать чем Ъ асинхронщина отличается от мультиплексоров.

asyncio в питоне это асинхронщина построенная на спрятанных тредах и мультиплексорах

redixin ★★★★ ()

Asyncio поможет если в параллели с опросом GPIO надо веб-морду показать и иметь возможность кнопочками в браузере с программой взаимодействовать. А так - делал на ESP8266+micropython включение/выключени по таймеру. Циклом - 5 строк. Без цикла (на местном event loop) - 50 строк (+ещё 100 строк на веб-сервер).

ei-grad ★★★★★ ()
Последнее исправление: ei-grad (всего исправлений: 1)
Ответ на: комментарий от redixin

В венде понимали, что бывают сетевые ФС и ФС на дискетах, а не только на быстрых локальных носителях и сделали нормальный асинхронный API для чтения файлов.

Но в ленсуке при сетевые ФС, похоже, до сих пор не в курсе.

anonymous ()
Ответ на: комментарий от alpha

Нет, не так.

Event loop — это когда ты вызываешь select() / poll() / epoll() в цикле. Каждая из этих функций блокирующая: ОС ставит твой поток на паузу и занимается другими делами. Когда в любом из переданных туда fd происходит «событие» (что такое «событие», определяется отдельно — обычно это или готовность для чтения, или готовность для записи, или исключительная ситуация типа обрыва канала), ОС ставит твой поток в очередь исполнения, и когда исполнение до него доходит, функция возвращает управление.

Со стороны потока это выглядит так, как будто выполнение select() заняло непредсказуемое количество реального времени.

intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 1)

Наконец,

В чем польза asyncio?

В идеальном случае, в конечном итоге этот твой ioctl выльется в то, что ядро поставит на GPIO обработчик прерывания и уйдёт спать. Когда на GPIO что-то случится, возникнет прерывание, которое по цепочке вернёт управление в твою программу. Профит понятен: процессор будет меньше крутиться в бесполезном цикле и больше спать, при этом сохраняется «мгновенность» реакции на событие.

В неидеальном случае где-то внутри драйвера GPIO всё равно может быть тот же самый поллинг. Тогда весь профит только в соблюдении принципа DRY.

intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от alpha

> Может monitor file i/o - это когда кто-то другой пишет/читает, а ты со стороны пытаешься определить что там происходит?

Нет.

То есть они говорят что monitor file descriptor for read availability и monitor file I/O - это совсем разные вещи.

Второе — это частный случай первого, когда fd получен из обычного файла.

loop.add_reader() and loop.add_writer() cannot be used to monitor file I/O

Насколько я понимаю, это о том, что говорит redixin: с точки зрения select()/poll()/epoll(), fd типа «файл» будет всегда «готов» к чтению или записи, поэтому использовать asyncio для асинхронной работы с файлами бессмысленно.

intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 2)