Skip to main content

Logo

Pyroxide

A lock-free, high-concurrency background task broker for Python, powered by Rust.

Rust Python License: MIT/Apache-2.0/Coffee

Explore the Docs »

API Reference · See Examples · Report Bug · Request Feature


Pyroxide (pyro3) is a lightweight, ultra-high-performance background task broker designed to bridge Python and Rust. It allows CPU-bound or blocking workloads to bypass the Python Global Interpreter Lock (GIL) with minimal memory overhead and zero CPU-sleep polling.

Why Pyroxide?

  • 🚀 Bypass the GIL (GIL-Free): Execute CPU-intensive compiled tasks on background OS threads without holding the Python GIL.
  • Microsecond Latency: Utilizes OS-level signaling (Condvar) rather than CPU-burning thread polling, dispatching and completing tasks in under 25 microseconds.
  • 📦 Zero Infrastructure: Runs completely in-process. No Redis, RabbitMQ, or Celery worker daemons to configure or maintain.
  • 💾 Zero-Copy Serialization: Pass large byte arrays, memoryviews, or columnar buffers across the C-ABI boundary without copy or pickle overhead.
  • 🛠️ On-the-Fly Native Compilers: Write code as Python strings and compile them to dynamic libraries on-the-fly (Rust, C, and Zig supported!) with automatic build tree cleanup and persistent binary caching.
  • 🛡️ Isolated Worker Processes: Opt-in isolated=True to run tasks in separate processes via cross-platform Named Pipes / Domain Sockets. Features bidirectional Zero-Copy Shared Memory (SHM) routing for payloads >= 1MB with RAII Drop-guard leak protection, and an auto-scaling Scale-to-Zero pool to reclaim memory.
  • 🛡️ WASM Resource Limits: Enforces strict execution time limits via epoch-based interruption to prevent infinite loop lockups, alongside store memory growth limits to prevent host process Out-Of-Memory (OOM) crashes.
  • ⚠️ Queue Exhaustion Safety: The task queue operates safely and bounded. Submissions block with configurable timeouts or immediately raise a Python BufferError if the queue is full, avoiding uncontrolled memory allocation.
  • 🔗 Task Groups & Workflows: Bundle multiple task handles into parallel groups (group) to await or cancel them as a single logical unit.

Pyroxide vs. Alternatives

Feature / Metric Pyroxide Threading (std) Multiprocessing Celery / RQ
GIL Bypass ✅ Yes (WASM/dylib) ❌ No ✅ Yes ✅ Yes
IPC / Serialization ✅ None (Shared Memory) ✅ None ❌ High (Pickling) ❌ High (Network/Redis)
Infrastructure ✅ None (Embedded) ✅ None ⚠️ Low (Spawns processes) ❌ High (Redis/RabbitMQ)
Best For 🔥 High-perf in-process pipelines I/O-bound Python CPU-heavy Python Distributed tasks

For a detailed analysis, check out the Library Comparison Guide.


Installation

From PyPI

pip install pyro3

Build Locally

Ensure you have Rust, Python (3.8+), and maturin installed:

git clone https://github.com/emivvvvv/pyroxide.git
cd pyroxide
pip install maturin
maturin develop

Quick Start

1. Offload Python Callables

from pyroxide import task

@task
def calculate_square(x: int) -> int:
    return x * x # Runs in background OS threads

# Submit and get a handle immediately
handle = calculate_square(12)
result = handle.result() # Blocks natively (0% CPU) until complete
print(result) # 144

# Pure Python tasks can fully bypass the GIL with `isolated=True`
@task(isolated=True)
def heavy_computation(x: int) -> int:
    return sum(i * i for i in range(x))

2. Batch Submission & Task Groups

Submit tasks in bulk under a single lock acquisition to avoid thread contention, and manage them concurrently:

from pyroxide import task, group

@task
def calculate_square(x: int) -> int:
    return x * x

payloads = [10, 20, 30, 40]

# 1. Batch submit payloads
handles = calculate_square.batch(payloads)

# 2. Bundle into a parallel TaskGroup
tg = group(handles)
print(tg.status) # "Running"

# 3. Retrieve results (consume=False preserves status metadata)
results = tg.result(consume=False)
print(results)   # [100, 400, 900, 1600]
print(tg.status) # "Completed"

3. Sandboxed WebAssembly (GIL-Free)

Run computations GIL-free in a secure, virtual sandbox without compiling native code:

from pyroxide import register_wasm, wasm_task, load_wasm

# 1. Register WebAssembly bytecode
with open("rot13.wasm", "rb") as f:
    register_wasm("rot13", f.read())

# 2. Execute via decorators
@wasm_task("rot13")
def rot13_cipher(payload: str) -> str:
    pass

print(rot13_cipher("hello").result()) # "uryyb"

# 3. Or load as an Object-Oriented Proxy!
cipher = load_wasm("rot13")
print(cipher.run("hello").result()) # "uryyb"

4. Dynamic Shared Libraries (On-the-Fly Compilation)

Compile and load native code strings on-the-fly. Rust (compile_dylib), C (compile_c), and Zig (compile_zig) are supported:

from pyroxide import compile_dylib, dylib_task, load_dylib

RUST_SRC = """
#[no_mangle]
pub unsafe extern "C" fn pyroxide_plugin_run(ptr: *const u8, len: usize, out_len: *mut usize) -> *mut u8 {
    let input = std::slice::from_raw_parts(ptr, len);
    let s = std::str::from_utf8(input).unwrap_or("");
    let result = s.to_uppercase().into_bytes();
    *out_len = result.len();
    let boxed = result.into_boxed_slice();
    Box::into_raw(boxed) as *mut u8
}

#[no_mangle]
pub unsafe extern "C" fn pyroxide_plugin_free(ptr: *mut u8, len: usize) {
    let _ = Box::from_raw(std::slice::from_raw_parts_mut(ptr, len));
}
"""

# Compile, register and load the Rust library on-the-fly!
compile_dylib("rust_upper", RUST_SRC)

# 1. Execute via decorators
@dylib_task("rust_upper")
def to_upper_rust(payload: str) -> str:
    pass

print(to_upper_rust("hello from rust").result())  # "HELLO FROM RUST"

# 2. Or load as an Object-Oriented Proxy to call any custom C-ABI symbol directly!
rust_upper = load_dylib("rust_upper")
print(rust_upper.pyroxide_plugin_run("hello from rust").result())  # "HELLO FROM RUST"

Dive Deeper (Documentation Book)

Detailed documentation, guides, and implementation examples are available in our Documentation Book:

  • Asynchronous Event Loops: Non-blockingly await tasks using await handle.result_async() in FastAPI/asyncio. Read Chapter.
  • Isolated Worker Processes: Sandbox tasks in separate OS processes for crash safety and GIL bypass. Read Chapter.
  • Batch Submissions: Submit multiple tasks under a single lock acquisition to avoid thread contention. Read Chapter.
  • Task Cancellation: Gracefully abort long-running background tasks mid-flight. Read Chapter.
  • Traceback Preservation: Capture stack traces on background worker threads and propagate them to the main thread. Read Chapter.
  • Memory Footprint & GC: Learn how Slab memory is reclaimed automatically using GC destructors. Read Chapter.

Performance At-a-Glance

We benchmarked Pyroxide against CPython's standard concurrency pools using identical compute payloads (recursive Fibonacci 20 workload) on Apple M1 Pro (8 cores, 16GB RAM):

Metric (500 Tasks) Pyroxide @dylib_task Pyroxide @task(isolated=True) Pyroxide @task Threading (std) Multiprocessing
Execution Time 0.0200 s 0.0769 s 0.3878 s 0.3742 s 2.0786 s
GIL Bypass ✅ Yes (GIL-Free) ✅ Yes ❌ No ❌ No ✅ Yes
IPC / Serialization ✅ None (Shared Memory) ✅ Zero-Copy SHM ✅ None ✅ None ❌ High (pickle cost)
Relative Speedup 🔥 100x faster 🔥 27x faster 5x faster 5x faster Baseline (1x)
  • Bypassing the Multiprocessing Bottleneck: While Python's ProcessPoolExecutor takes over 2 seconds due to slow process spawning and heavy pickle IPC serialization, Pyroxide's @dylib_task runs native compiled plugins in just 20 milliseconds—offering a 100x speedup with zero-copy shared memory.

Real-World Odoo Enterprise Arrow Ledger Audit Benchmark

To test performance under realistic enterprise data movement workloads, we ran a simulated Odoo Ledger Audit benchmark processing a 9.62 MB Apache Arrow serialized transaction recordset (200,000 journal items) across 10 concurrent requests comparing different concurrency strategies:

  • CPython ThreadPoolExecutor (GIL-Locked): 0.3221 s
  • Pyroxide Threaded @task (GIL-Locked): 0.3298 s (matches Python's native scheduling overhead perfectly)
  • ProcessPoolExecutor (Python, Pickled Pipes): 0.2758 s
  • Pyroxide SHM Isolated @task (Zero-Copy SHM): 0.3272 s
  • Pyroxide @dylib_task (C-compiled, GIL-Free): 0.0091 s (bypasses GIL entirely)

Key Takeaway: By offloading the audit logic to a dynamically compiled C/Rust plugin running on Pyroxide's background thread pool, we achieve a 35.3x speedup over CPython's standard ThreadPoolExecutor by completely bypassing the GIL.

To run the Odoo simulation suite locally:

python examples/odoo_poc/odoo_complex_simulation.py

To run the comparative and basic benchmark suites locally:

# 1. Run detailed comparative benchmarks against CPython concurrency pools
python examples/benchmarks/benchmark_vs_alternatives.py

# 2. Run basic scheduling latency and asyncio benchmarks
python examples/benchmarks/benchmark.py

Contributing

Contributions are welcome! If you'd like to improve Pyroxide or add support for additional features, feel free to open an issue or submit a pull request on GitHub.

License

Pyroxide is licensed under any of:

at your option.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyro3-0.6.1.tar.gz (100.8 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pyro3-0.6.1-cp38-abi3-win_amd64.whl (3.4 MB view details)

Uploaded CPython 3.8+Windows x86-64

pyro3-0.6.1-cp38-abi3-manylinux_2_39_x86_64.whl (4.3 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.39+ x86-64

pyro3-0.6.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.1 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ARM64

pyro3-0.6.1-cp38-abi3-macosx_11_0_arm64.whl (3.7 MB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

pyro3-0.6.1-cp38-abi3-macosx_10_12_x86_64.whl (3.9 MB view details)

Uploaded CPython 3.8+macOS 10.12+ x86-64

File details

Details for the file pyro3-0.6.1.tar.gz.

File metadata

  • Download URL: pyro3-0.6.1.tar.gz
  • Upload date:
  • Size: 100.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: maturin/1.14.1

File hashes

Hashes for pyro3-0.6.1.tar.gz
Algorithm Hash digest
SHA256 6c2d054208c449cd4a484febfaecb732b9124e613560ffd1e6315d7d32cb0e0b
MD5 4f527d797202cd63d95563208352ac52
BLAKE2b-256 c307fd7a8d00d1fad851da523f19fbfd3144f07e2c8bc3c016ed1ac5d74f0744

See more details on using hashes here.

File details

Details for the file pyro3-0.6.1-cp38-abi3-win_amd64.whl.

File metadata

  • Download URL: pyro3-0.6.1-cp38-abi3-win_amd64.whl
  • Upload date:
  • Size: 3.4 MB
  • Tags: CPython 3.8+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: maturin/1.14.1

File hashes

Hashes for pyro3-0.6.1-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 6050a0e3b0c2b27e772e8d4ebe1d5ce9e1b05ef4c16ae1d7d5aed9bd29bda120
MD5 a986032a4ff89c0fbd387744371334f0
BLAKE2b-256 ca06925a47354086835814654f9fa0435b72550efefd7e47a9f449083fe92f76

See more details on using hashes here.

File details

Details for the file pyro3-0.6.1-cp38-abi3-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for pyro3-0.6.1-cp38-abi3-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 7667c88ee97d76d6a33b9c4d9369a1497706765dc005145612bd7bb80679609a
MD5 7605e4372ae6e075c2b8f27d60c6c986
BLAKE2b-256 26b269003ff6805179fb14e02bc20830551576de8a2b7217f62cae8f82476154

See more details on using hashes here.

File details

Details for the file pyro3-0.6.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pyro3-0.6.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 a5a526f131eb8c46370f5b6c0f71fe28651c964ab30d96c779ba4b8fe9111806
MD5 84ebaa96ce020c858055c5c8452a6450
BLAKE2b-256 97bfb7c8c82ced1449cfae964ea804b4685ec6382f6fb7e935f6c9f6130d276c

See more details on using hashes here.

File details

Details for the file pyro3-0.6.1-cp38-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyro3-0.6.1-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 33c931c1c18edf6ed4ce187721d467f489ef426741d60bea9e743e2575509f6c
MD5 eb6099d0583c5ec5e5351f5af854e279
BLAKE2b-256 f2f648f4e4fb620480798a364231a1cd5f2317ee2b368b69fcac28bc2f0ab4e7

See more details on using hashes here.

File details

Details for the file pyro3-0.6.1-cp38-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for pyro3-0.6.1-cp38-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 acbc71b800bf2460ce3edc5e672f5e3e7bf5875dbdf3055f356dfb20e6517c1b
MD5 49531e7b0383ba5336a358c83d8bf4af
BLAKE2b-256 565b5c7e9ef7151a1a44f344d7419d064dc4bb5c19a4cea1c6cf6a7e8c91c10f

See more details on using hashes here.

Release history Release notifications | RSS feed

0.8.3

6 files

0.8.2

6 files

0.8.1

6 files

0.8.0

6 files

0.7.0

6 files

This release

0.6.1 This release

6 files

0.6.0

6 files

0.5.2

6 files

0.5.1

6 files

0.5.0

6 files

0.4.0

6 files

0.3.3

6 files

0.3.2

4 files

0.3.1

4 files

0.3.0

4 files

0.2.1

4 files

0.2.0

4 files

0.1.3

4 files

0.1.2

4 files

0.1.1

4 files

0.1.0

4 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page