Module pywaker

Module pywaker 

Source
Expand description

Pywaker provides a GIL-free way to wake up Python event loops from Rust. This is accomplished by writing a single byte to a “self pipe” for every wake up. The corresponding read-side FD is added to the Python-side event loop.

The approach does not add overhead in uncontended scenarios:

  | Approach             | Mean   | Notes                           |
  |----------------------|--------|---------------------------------|
  | FD-based             | ~48 µs | No GIL acquisition on Rust side |
  | call_soon_threadsafe | ~56 µs | Acquires GIL on Rust side       |
  | Pure Python          | ~44 µs | Baseline for comparison         |

(Full benchmarks).

§Implementation notes

event creates a pipe(2), and wakeup events are implemented by writing a single byte into the pipe. The Python (read side) event registers the read fd into its asyncio event loop. Thus the pipe acts as a notification queue. When the fd becomes readable, the python event drains the pipe and then sets an asyncio.Event to notify any waiters.

The reader side is always single threaded (it is bound to a specific event loop), and thus free of race conditions. This is because all read operations occur within a single asyncio event loop, which processes events sequentially on one thread, eliminating the possibility of concurrent access to the read side of the pipe.

Structs§

PyEvent
An event that is awoken by a Waker.
Waker
Waker is is a handle to a PyEvent.

Functions§

event
Create a new event, returning the (Rust only) Waker, and a Python PyEvent, intended for passing to Python code.
register_python_bindings