Size: a a a

2020 June 14

АГ

Алексей Герасимов... in Rust Async
сам спокойно использовал токийские возможности (файлы, раббит, reqwest, s3), но у меня не было требования к single-thread нигде, так что тут не копенгаген так сказать
источник

G

George in Rust Async
Существует простой способ активировать рантайм из синхронной функции? (если нет возможности использовать иное)
Вообще хотелось бы попросить совет.
Условия: например, используется ffi, либо другие причины синхронности исполняемой работы. Задача: запустить (относительно) короткоживущий (несколько секунд, в худшем случае несколько десятков на ну очень тяжелых запросах в базу) асинхронный рантайм(токио, по крайней мере сейчас) в этом же или другом потоке(без разницы), так как уже из нескольких запросов в БД/сеть с помощью join можно получить преимущество, сделать эти запросы, что-то сделать с данными и вернуть в синхронную функцию, а оттуда в вызывающий интерфейс/синхронный код. Такое возможно без совсем извращений?
источник

n

not a cake in Rust Async
Алексей Герасимов
сам спокойно использовал токийские возможности (файлы, раббит, reqwest, s3), но у меня не было требования к single-thread нигде, так что тут не копенгаген так сказать
Требования к одному треду в актикса, не у меня. Там возможно, чтобы акторы общались, находясь в разных воркер-тредах, но это надо делать, чтобы в каждом воркере tokio жил actix::Arbiter и вообще, чтобы оно вместе работало. Но поскольку у меня нет нужды юзать много тредов, то попробую обойтись actix-rt
источник

n

not a cake in Rust Async
George
Существует простой способ активировать рантайм из синхронной функции? (если нет возможности использовать иное)
Вообще хотелось бы попросить совет.
Условия: например, используется ffi, либо другие причины синхронности исполняемой работы. Задача: запустить (относительно) короткоживущий (несколько секунд, в худшем случае несколько десятков на ну очень тяжелых запросах в базу) асинхронный рантайм(токио, по крайней мере сейчас) в этом же или другом потоке(без разницы), так как уже из нескольких запросов в БД/сеть с помощью join можно получить преимущество, сделать эти запросы, что-то сделать с данными и вернуть в синхронную функцию, а оттуда в вызывающий интерфейс/синхронный код. Такое возможно без совсем извращений?
https://docs.rs/tokio/0.2.21/tokio/runtime/struct.Runtime.html#method.block_on
Это не подойдет? На месте в текущем треде делаешь сам Runtime (можно как в примере, а можно заюзать tokio::runtime::Builder и самому кое-какие его параметры определить), а результат из async блока будет тебе синхронно возвращен. Не пользовался, но похоже, так оно и есть
источник

n

not a cake in Rust Async
Если же вызовов твоей синхронной функции будет немало, стоит наверное один раз создать рантайм и потом его переиспользовать. Здесь мне в голову приходит lazy_static! { ... } для его одноразовой инициализации, возможно еще какой-то лок надо будет на него ставить, глобальный всё-таки. По этому поводу лучше посмотреть, как в tokio по умолчанию он глобально хранится (если это вообще так)
источник

D

Denis in Rust Async
not a cake
https://docs.rs/tokio/0.2.21/tokio/runtime/struct.Runtime.html#method.block_on
Это не подойдет? На месте в текущем треде делаешь сам Runtime (можно как в примере, а можно заюзать tokio::runtime::Builder и самому кое-какие его параметры определить), а результат из async блока будет тебе синхронно возвращен. Не пользовался, но похоже, так оно и есть
всё так, получившийся Runtime можно, например, хранить в каком-нибудь статике
чтобы запускать функции, требующие токио, надо просто вызывать их внутри Runtime::enter
источник

D

Denis in Rust Async
once_cell::sync::Lazy достаточно
источник

D

Denis in Rust Async
Runtime::enter принимает &self, так что и синхронизации никакой не нужно
источник

G

George in Rust Async
Вообще штука получается такая:
Python_async_fn -> rust_sync_ffi_обёртка -> rust_sync_запуск_асинка -> rust_async_* -> N , где * - асинхронная функция, запускающая N других функций(requwest, база). То есть lazy_static!() не понадобится, так как каждый раз будет новое обращение к сошке, а не стабильный рантайм. Наверное.

Другое дело: контейнер на N воркер-процессов, где .so раста будет в единственном экземпляре. Вот что будет тут я не знаю, плюс, так как Python тоже асинхронный, он может запустить несколько синхронных ffi-функций через прослойки собственного рантайма и ждать их из многих мест.
Мне уж начало казаться, что проще держать карманный actix, куда ходить по http(в пределах одного и того же контейнера, ужас конечно), дабы не париться с этими рантаймами, но конкретно в Rust мне не хватает опыта о том, как лучше сделать и как вообще будет работать такое нагромождение прослоек.
источник

D

Denis in Rust Async
что значит "новое обращение к сошке"? ты каждый раз делаешь dlopen/dlclose? :) подозреваю, что всё-таки один раз, так что можно и не пересоздавать рантайм каждый раз

достаточно сделать глобальную переменную once_cell::sync::Lazy<Runtime> и обращаться к ней
источник

D

Denis in Rust Async
очень советую сначала попробовать на минимальном примере
источник

D

Denis in Rust Async
кажется, что никаких проблем быть не должно
источник

G

George in Rust Async
Новое обращение = 4-8-16 воркеров заходят дёрнуть один и тот же файл, ну вот пришло столько запросов, что надо сходить в ffi всем. При запуске функций каждый раз будет новый поток ОС с новым рантаймом?
в ffi лежит единственная синхронная функция, которая этот рантайм запускает. Нет постоянно запущенного чего-то, только динамическая библиотека и дёрганье её функций. С компилируемыми языками не очень знаком, static/dynamic libraries не очень шарю как работают в таких условиях. Компилится всё в cdylib, как в гайдлайнах pyo3.
источник

D

Denis in Rust Async
ммм
источник

D

Denis in Rust Async
> Нет постоянно запущенного чего-то
источник

D

Denis in Rust Async
то есть каждый раз питоновский скрипт запускается "с нуля"?
источник

G

George in Rust Async
Нет постоянно запущенного чего-то со стороны раста, он либа. Используются долгоживущие воркеры питона, которых спавнит родитель, но в рамках одного контейнера. Самый обычный сервер uvicorn. Долгоживущие воркеры дёргают rust в качестве ffi - mixed rust/python project тобишь. На данный момент я сделал не очень много - минимальная обёртка, структура, три работающих самых обычных метода с обёрткой в pymodule. И вот в этих самых обычных методах необходимо создавать рантайм. Вот я и задаюсь вопросом, как это работает и не будет ли накладно.
источник

D

Denis in Rust Async
питон подгружает либу один раз
источник

D

Denis in Rust Async
так что если питон живёт, то и растовые штуки тоже будут жить )
источник

G

George in Rust Async
Denis
так что если питон живёт, то и растовые штуки тоже будут жить )
То есть это значит, что имеет смысл содержать ленивый рантайм? Сложно, конечно. Там ещё свои грабли, связанные с pyo3... Может как закончу функцию функционально, либо минимальный пример, забегу ещё. Спасибо за ответы.
источник