rsloop is a PyO3-based asyncio event loop implemented in Rust.
Each rsloop.Loop owns a dedicated Rust runtime thread for loop coordination
and I/O work. That thread runs an rsloop-specialized vibeio runtime, using
io_uring on Linux, IOCP on Windows, and native kqueue readiness on macOS.
Native-stream TCP reads and Unix-domain socket reads run on that runtime. On Unix, generic
TCP protocol readers use a second vibeio runtime on the Python loop thread
(io_uring on Linux), avoiding cross-thread delivery of each read. Non-TLS accepts
run on either runtime depending on where the server starts. Python callbacks,
tasks, and coroutines run on the thread that calls
run_forever() or run_until_complete() (usually the main Python thread).
The package exposes:
- a native extension module at
rsloop._loop - a Python wrapper in
python/rsloop/__init__.py rsloop.Loop,rsloop.EventLoopPolicy,rsloop.new_event_loop(),rsloop.run(...),rsloop.install(),rsloop.uninstall(), andrsloop.build_info()
Repository metadata supports CPython 3.10 through 3.15.
The native runtime requires Linux 6.1+, macOS 13+, or Windows 10+ so its hot
paths can rely on modern completion, timer, and scheduler primitives.
Free-threaded CPython (3.14t) is supported: the extension declares
gil_used = false, so importing it no longer re-enables the GIL. See
Free-Threaded CPython for what that does and does not
buy you.
Project documentation now lives in docs/.
If you are new to the repository, start with:
docs/index.mddocs/getting-started.mddocs/supported-features.mddocs/fast-streams.mddocs/free-threading.mddocs/rust-extensions.mddocs/how-it-works.mddocs/project-structure.mddocs/development.mdfor building, testing, and profiling
To browse the docs locally with MkDocs:
uvx --from mkdocs mkdocs serveFrom PyPI:
pip install rsloopWith uv:
uv add rsloopFrom conda-forge, using pixi:
pixi add rsloopSimple entry point:
import rsloop
async def main(): ...
rsloop.run(main())Install as the default asyncio event loop policy:
import asyncio
import rsloop
rsloop.install()
try:
asyncio.run(main())
finally:
rsloop.uninstall()Manual loop creation also works:
import asyncio
import rsloop
loop = rsloop.new_event_loop()
asyncio.set_event_loop(loop)
try:
loop.run_until_complete(...)
finally:
asyncio.set_event_loop(None)
loop.close()Importing rsloop also patches asyncio.set_event_loop() so Python 3.10 can
accept an rsloop.Loop instance, matching the behavior exercised by
tests/test_run.py.
Run the repository examples from the project root:
uv run python examples/01_basics.py
uv run python examples/02_fd_and_sockets.py
uv run python examples/03_streams.py
uv run python examples/04_unix_and_accepted_socket.py
uv run python examples/05_pipes_signals_subprocesses.pyExample files:
examples/01_basics.py,
examples/02_fd_and_sockets.py,
examples/03_streams.py,
examples/04_unix_and_accepted_socket.py,
examples/05_pipes_signals_subprocesses.py.
The repository also includes:
examples/fastapi_service.pyfor running the same FastAPI app on stdlibasyncio,uvloop, orrsloopexamples/granian_service.pyfor registeringrsloopas Granian's worker event loopbenches/compare_event_loops.pyfor callback, task, and TCP stream comparisonsbenches/compare_granian.pyfor Granian HTTP throughput and latency comparisons withoha
See benchmark results and reproduction commands.
rsloop builds on the Python asyncio model and is implemented with
PyO3 on the Rust side. Runtime and socket I/O are powered by
vibeio.
This project is licensed under the Apache License, Version 2.0. See
LICENSE for the full text.
