Runloom: Go-style Coroutines for Free-Threaded Python 3.13t+

Runloom: Go-style Coroutines for Free-Threaded Python 3.13t+

Runloom provides Go-style stackful coroutines (fibers) for Python, allowing developers to write blocking-style code that executes concurrently across all available CPU cores. By leveraging free-threaded Python (GIL-off) in versions 3.13t and 3.14t, Runloom enables a single process to manage millions of fibers using a high-performance C-based work-stealing scheduler.

High-Performance M:N Scheduling

Runloom implements an M:N work-stealing scheduler that maps many fibers onto a smaller number of OS threads (hubs). This architecture allows Python applications to achieve massive concurrency without the syntactic overhead of async/await.

Key technical components include:

  • Hand-rolled Assembly Context Switching: Uses x86_64 SysV and aarch64 assembly for context swaps (~80 ns/swap) without requiring system calls. Fallbacks include Windows Fibers and POSIX ucontext.
  • Work-Stealing Scheduler: Employs a Chase-Lev deque per hub and per-hub MPSC submission to balance load across cores.
  • Netpoll Integration: Integrates epoll, kqueue, IOCP, WSAPoll, and select to park goroutines transparently on file descriptor readiness.
  • PyThreadState Snapshots: Captures the cframe, datastack, exc_info, contextvars, and recursion state for each fiber, preventing the "frame-chain cliff" when millions of fibers are yielded.

Performance Benchmarks vs. Go

In benchmarks conducted on a 64-core machine using free-threaded CPython 3.13t, Runloom demonstrates performance parity with Go in several critical areas, though it maintains a higher memory footprint.

Metric Runloom Go Verdict
Spawn (Pure C) 2.29 M/s 2.10 M/s Beats Go
Spawn (Python API) 1.35 M/s 2.10 M/s 0.65×
Context Switch ~75ns yield / ~560ns chan RT ~50ns Gosched Parity
Conn/s (Churn) ~75–78 k/s ~75–78 k/s Parity
Req/s (Keep-alive) 596 k/s 603 k/s 0.99× (Parity)
Memory (Empty Fiber) 8.8 KB 2.7 KB 3.3×

While Runloom matches Go on throughput and scheduling, the primary gap is memory: a suspended fiber requires approximately 3.3× more RAM than a Go goroutine because it must carry a CPython eval frame.

Integration and Compatibility

Runloom is designed to be minimally invasive to existing codebases through several integration paths:

Blocking Code Transformation

By using runloom.monkey.patch(), standard library calls in socket, time, and threading become cooperative. This allows existing blocking code to run concurrently across real cores without modification.

Asyncio Bridge

For projects already using async def, the runloom.aio bridge allows asyncio code to run on the Runloom scheduler. However, this is a zero-rewrite port path and does not provide multi-core speedups; multi-core parallelism requires the synchronous API and run(n > 1, main).

Technical Limitations

Runloom's performance is bound by the underlying Python interpreter and the specific build used:

  • Free-Threaded Requirement: To achieve multi-core wins, Python 3.13t (or 3.14t) is required. On standard GIL builds, Runloom remains single-core, behaving similarly to asyncio.
  • Per-Core Speed: Runloom does not increase the raw execution speed of Python bytecode; it simply allows that speed to be utilized across every available core simultaneously.
  • Preemption: Preemption occurs only at Python bytecode boundaries. A fiber executing a tight loop in a pure-C extension (like numpy) will hold its hub until the C call returns.
  • Platform Focus: While supporting multiple OSs, Linux x86_64 on 3.13t is the primary, heavily-validated target.

Community Perspective

Early reactions to the project highlight both its technical ambition and the caution required for new, complex runtimes. Some observers note that the project's scale—comprising over 12,000 lines of C and 240,000 lines of Python—is significant for a new release, leading to questions regarding long-term stability and trust.

Other developers have compared it to gevent, noting that Runloom's ability to leverage the no-GIL (free-threaded) architecture makes it a more modern and powerful alternative for multi-core parallelism.

Sources