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?

  • 🚀 GIL-Free Performance: Execute CPU-intensive tasks on background threads or isolated processes without holding the Python GIL.
  • Microsecond Latency: Dispatch and complete tasks in under 25 microseconds using OS-level signaling (Condvar) instead of polling.
  • 📦 Zero Infrastructure: Run entirely in-process with no Redis, RabbitMQ, or Celery worker daemons to configure or maintain.
  • 💾 Zero-Copy Transport: Route large payloads ($\ge 1\text{MB}$) via OS Shared Memory (SHM) to bypass serialization copying bottlenecks.
  • 🛡️ Sandbox & Queue Safety: Enforce memory/time limits on WASM tasks to prevent OOM/hangs, and use bounded queues to avoid memory runs.
  • 🛠️ Dynamic FFI Compilation: Compile code strings on-the-fly (Rust, C, Zig) into native libraries with persistent binary caching.

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_rust), C (compile_c), and Zig (compile_zig) are supported:

from pyroxide import compile_rust, 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_rust("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. Reusing a pre-compiled system library (Universal FFI)
# Load system math library natively - no pyroxide_plugin_free required for primitives!
import sys
libm_name = "libm.dylib" if sys.platform == "darwin" else "libm.so.6"
libm = load_dylib(libm_name, signatures={
    "cos": {"args": ["f64"], "ret": "f64"}
})
print(libm.cos(3.1415926535).result())  # -1.0

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"


### 5. Programmatic Sandbox Configuration (v0.7.0)
Configure WebAssembly memory limits, execution timeouts, and queue block/drop timeouts thread-safely:
```python
import pyroxide

# Set global default sandbox parameters
pyroxide.config.set_wasm_limits(memory_limit_bytes=50 * 1024 * 1024, timeout_ms=500)
pyroxide.config.set_queue_timeout(timeout_ms=100)

# Apply context-specific overrides (thread-safe, ideal for multi-tenant SaaS)
with pyroxide.config.scoped(wasm_timeout_ms=50, wasm_memory_limit_bytes=10 * 1024 * 1024):
    handle = rot13_cipher("hello")

6. Static Stub Compilation CLI (v0.7.0)

Avoid runtime filesystem writes during application startup (which triggers FastAPI reload loops) by statically building type stubs:

# Scan Python files recursively to generate proxy .pyi stubs
pyroxide build-stubs --scan --scan-dir . --out-dir .

# Or read declarative configuration from pyproject.toml
pyroxide build-stubs

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.8.0.tar.gz (109.6 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.8.0-cp38-abi3-win_amd64.whl (3.4 MB view details)

Uploaded CPython 3.8+Windows x86-64

pyro3-0.8.0-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.8.0-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.8.0-cp38-abi3-macosx_11_0_arm64.whl (3.7 MB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

pyro3-0.8.0-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.8.0.tar.gz.

File metadata

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

File hashes

Hashes for pyro3-0.8.0.tar.gz
Algorithm Hash digest
SHA256 12c2d0bd8c9a32dc3836255d69581a2c313e9e483a98994a58f2c27ef306dd01
MD5 05ce69d7599664ac0c0a42362f33bdd1
BLAKE2b-256 77c3dd9361dd0de06f7e53533599e33c7d72e35a9a62dd810c01dca8be575660

See more details on using hashes here.

File details

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

File metadata

  • Download URL: pyro3-0.8.0-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.8.0-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 227e2d0c457a37886918587d9b351a75eb98190494972d943ec1e0796f1bd494
MD5 9c48045b66ac47040dd072e189f198e9
BLAKE2b-256 4441d03c8763d085292d6ec022bd2bd8e818d68e19fc419a8b4d9ba17475f9ae

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pyro3-0.8.0-cp38-abi3-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 e017c18874802ac518e0a8cde95fa95d399522ad93f665ec71b2f6a336af0e8f
MD5 bdd08f64178c3d537bc1ce66f4804e83
BLAKE2b-256 c2a289ec70b597d2a71cc67b0eb88be1bdf435d60ede33521305854bcdf85b83

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pyro3-0.8.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 66be0b22c2591fa8c1a2a93dc24df4040d3397eded94872a97750b9f2585af08
MD5 7700056dbd5c8e3d3688c0db1f0d6a55
BLAKE2b-256 fd7449fdd26eaaf6bbf00aa4a78b319fa5a78fdf0977fbfc29d4d5a878013384

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pyro3-0.8.0-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 989f767dc8fbab120ecee2177b104bf5f05df6bb2dfe3cf5d4880362a64e3c64
MD5 0b935d84abd28a94419ce689e9e8ab09
BLAKE2b-256 fd8cfae8be03ff72e2a6f50bfead24372953dc1e0471720f2ddfdcaf55e805da

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pyro3-0.8.0-cp38-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 3531e7e870f153b2f1afef83b11dfd73a88d7f011fcbb6ac6b7974028e917d51
MD5 8a0c0f7a4b747380b5b8feb776b46d15
BLAKE2b-256 8029d2e74e388009360152cbd62be62023cf3fe903e83000659f4e6909cd413b

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

This release

0.8.0 This release

6 files

0.7.0

6 files

0.6.1

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