Other async file libraries dispatch every call to a thread pool. turbofile submits the I/O to the kernel (io_uring on Linux, POSIX AIO on macOS) and completes your await when the kernel says the data moved. Same API as aiofiles.
PYTHON ≥ 3.12 · RUST CORE · MIT OR APACHE-2.0
SAME CALLS AS AIOFILES · COMPLETED BY THE KERNEL
An asyncio application does many small operations in flight, not one giant read. That is the workload where kernel submission beats a thread pool.
Apple-silicon Mac, macOS 26.4, POSIX AIO backend, page-cache-hot files. Large sequential transfers are memory-bandwidth-bound, so every implementation converges there; the wins are where per-op overhead and concurrency dominate. Run make bench for your hardware.
Binary and text modes, encoding/errors/newline, seek and tell, readline, async iteration, readinto, truncate, fsync. For the open API, import turbofile as aiofiles is the whole migration.
SWAP IT INReads: the kernel fills the bytes object your await returns. Writes: your buffer is pinned and the kernel gets its pointer. No intermediate copies on the hot paths.
SEE THE NUMBERSA burst of completions costs a single event-loop wakeup, drained entirely in Rust. Large reads split into chunks the kernel fills concurrently into one buffer.
MEET THE BACKENDSKnown limitations, straight from the README
Selection is automatic. TURBOFILE_BACKEND=compio overrides it on macOS. Windows (IOCP via compio) is planned.
io_uring submission and completion rings, with an automatic polling fallback under seccomp or older kernels.
aio_read, aio_write and aio_fsync, served by XNU. Kernel-serviced async I/O, not a thread pool.
The compio kqueue driver with thread dispatch, for benchmarking or as an escape hatch if POSIX AIO misbehaves on your setup.