Date: 2026-07-30
Environment: Linux x64, 32 cores, Node v24.18.0, Python 3.12.13
Method: Same process, same mock server, fixed responses, N=200-300 runs to take statistical values
bench scripts: bindings/node/bench/, bindings/python/bench/
Same abstraction layer (HTTP + JSON, no orchestration/schema validation/middleware), clean numbers.
| mean | P50 | P95 | P99 | RSS growth |
|---|
| aimux (napi → Rust → reqwest) | 0.101ms | 0.096 | 0.122 | 0.139 | +2MB |
| OpenAI Node SDK (undici) | 1.488ms | 1.500 | 1.637 | 1.923 | +17MB |
| Multiple | | | | | |
| aimux faster | 14.7x | | | | memory saves 8.5x |
| mean | P50 | P95 | P99 | RSS growth |
|---|
| aimux (PyO3 → Rust → reqwest) | 0.080ms | 0.075 | 0.108 | 0.129 | +0MB |
| OpenAI Python SDK (httpx) | 0.595ms | 0.577 | 0.695 | 0.839 | +8MB |
| Multiple | | | | | |
| aimux faster | 7.5x | | | | memory saves ∞ |
| Scenario | SDK | rps | mean | P99 | tail jitter (P99-P50) | RSS growth |
|---|
| 32 cores | aimux | 1512 | 0.66ms | 1.92ms | 1.31ms | +23MB |
| AISDK | 563 | 1.78ms | 3.96ms | 2.23ms | +103MB |
| 2 cores | aimux | 1583 | 0.63ms | 1.74ms | 1.14ms | +20MB |
| AISDK | 566 | 1.76ms | 5.73ms | 4.00ms | +144MB |
| 1 core | aimux | 1497 | 0.67ms | 1.65ms | 1.03ms | +21MB |
| AISDK | 473 | 2.11ms | 12.87ms | 11.20ms | +60MB |
| rps | mean | P99 | RSS growth | RSS trend |
|---|
| aimux | 1393 | 0.72ms | 0.94ms | +0MB | perfectly flat line |
| OpenAI SDK | 987 | 1.01ms | 1.37ms | +8MB | continuous slow growth |
| payload | JS stringify | JS parse | napi total | FFI boundary | Rust+HTTP |
|---|
| 1KB | 0.001ms | 0.001ms | 0.156ms | 0.002ms | 0.154ms |
| 10KB | 0.006ms | 0.004ms | 0.155ms | 0.010ms | 0.144ms |
| 100KB | 0.082ms | 0.051ms | 0.479ms | 0.133ms | 0.347ms |
| 500KB | 0.461ms | 0.376ms | 2.552ms | 0.837ms | 1.715ms |
| 1MB | 0.964ms | 0.717ms | 5.550ms | 1.680ms | 3.870ms |
Serialization accounts for ~50% under large payloads, but in real LLM requests (3-10s) it accounts for <0.1%, not worth optimizing.
| Comparison | Multiple | Apples-to-apples | Notes |
|---|
| vs OpenAI Node SDK | 14.7x | ✅ apples-to-apples | Both are HTTP + JSON, no orchestration layer |
| vs OpenAI Python SDK | 7.5x | ✅ apples-to-apples | Same as above |
| vs Vercel AI SDK | 11.1x | ❌ not apples-to-apples | AISDK includes zod validation/middleware/telemetry, 11x is inflated |
Vercel AI SDK does extra work per request: Zod schema validation, building a typed object tree, fetch middleware pipeline, telemetry recording. These accumulate in the V8 heap, causing memory bloat. aimux does none of these — the design goal is a lightweight access layer, not orchestration.
| Metric | Node.js (napi) | Python (PyO3) |
|---|
| aimux single request | 0.101ms | 0.080ms |
| aimux RSS (2000 req) | +2MB | +0MB |
| Source of advantage | Rust reqwest + connection pool | Same as left + PyO3 FFI is lighter |
Python aimux is faster than Node aimux — PyO3 calls Rust directly at the C API layer (nearly zero-overhead C function calls), while napi has to go through V8's napi_env/napi_value wrappers. Python's reference counting is also more memory-stable than V8 GC.
- aimux is the absolute leader on both sides: Node 14.7x, Python 7.5x
- Zero memory growth: Python aimux RSS did not grow by a single byte after 2000 requests; Node +2MB
- GC pauses: aimux has no GC, P99 tail jitter does not change under CPU constraints; AISDK's P99 spikes to 12.87ms on 1 core
- Serialization is not the bottleneck: in real LLM requests (3-10s), serialization overhead accounts for <0.1%
- Lightweight is the design goal: aimux does no orchestration/schema validation/middleware/telemetry, only the access layer — this is part of the source of the performance advantage, and also the product positioning