diff --git a/BENCHMARKS.md b/BENCHMARKS.md index 44e6a00e..2c4fbc6f 100644 --- a/BENCHMARKS.md +++ b/BENCHMARKS.md @@ -109,9 +109,11 @@ series through three indicators chosen by call-signature archetype — `SMA(20)` (1-in → 1-out), `ATR(14)` (multi-in → 1-out) and `MACD(12,26,9)` (1-in → multi-out). Two things fall out of the numbers: -- **Batch converges.** A `batch` call crosses the boundary once and the Rust core - computes the whole series internally, so batch throughput is roughly the same - in every binding — close to the core speed. +- **Batch crosses once.** A `batch` call crosses the boundary a single time and the + Rust core computes the whole series internally, so batch throughput stays high for + most bindings — the exceptions are the ones that copy or box the result array on + the way out (Node's JS `Array`, Python's stdlib `array.array` now that NumPy is + optional). - **Streaming reveals the boundary.** A per-tick `update` crosses the boundary once per value, so streaming throughput is where the bindings differ: the raw C ABI and P/Invoke-style calls are nearly free, while managed or interpreted @@ -126,23 +128,23 @@ AMD Ryzen 9 9950X): | Target | streaming (Mupd/s) | batch (Mupd/s) | |----------------------|-------------------:|---------------:| -| Rust core (no FFI) | 391 | 500 | -| C / C++ | 383 | 330 | -| C# | 337 | 244 | -| Python | 33 | 488 | -| Java | 28 | 175 | -| Go | 24 | 400 | -| WASM | 19 | 167 | -| Node.js | 17 | 10 | -| R | 0.1 | 193 | +| Rust core (no FFI) | 380 | 498 | +| C / C++ | 365 | 358 | +| C# | 348 | 259 | +| Python | 31 | 46 | +| Java | 38 | 173 | +| Go | 23 | 394 | +| WASM | 21 | 169 | +| Node.js | 16 | 9 | +| R | 0.1 | 279 | -Streaming spans more than three orders of magnitude — the raw C ABI (383) is -nearly the FFI-free Rust ceiling (391), while R's per-call interpreter overhead -(0.1) makes streaming ~2000× slower than its own batch. Batch converges near the -core speed for the zero-copy bindings (numpy, slices, typed arrays); the two -outliers are Node — whose napi `batch` boxes every element into a JS `Array` — -and R. These are machine-dependent and reflect FFI overhead, not algorithm -speed. +Streaming spans more than three orders of magnitude — the raw C ABI (365) sits +just under the FFI-free Rust ceiling (380), while R's per-call interpreter overhead +(0.1) makes streaming ~2800× slower than its own batch. Batch stays high for the +bindings that hand back a contiguous buffer (slices, typed arrays); the two low +outliers are Node — whose napi `batch` boxes every element into a JS `Array` — and +Python, which now copies into a stdlib `array.array` since NumPy became optional. +These are machine-dependent and reflect FFI overhead, not algorithm speed. These are throughput numbers, not competitive numbers — the "Wickra is fast" claim lives in sections 1 and 2 (Rust core + the Python/Rust cross-library runs). diff --git a/README.md b/README.md index 05936e41..47c99c0e 100644 --- a/README.md +++ b/README.md @@ -153,21 +153,21 @@ Full tables (Rust + Python, streaming + batch) and how to reproduce them live in Every binding calls the **same** Rust core, so this is **not** a speed claim — it is the raw cost of crossing each language's FFI boundary (`SMA(20)`, 200 000 bars, -Ryzen 9 9950X, million updates/sec). **Batch is near-core everywhere; streaming is -where the boundary shows** — so if you stream tick-by-tick, the table tells you -which binding keeps up and which to avoid for hot loops. +Ryzen 9 9950X, million updates/sec). **Batch stays high for most bindings; +streaming is where the boundary shows** — so if you stream tick-by-tick, the table +tells you which binding keeps up and which to avoid for hot loops. | Language | streaming (Mupd/s) | batch (Mupd/s) | |-----------------|-------------------:|---------------:| -| Rust (no FFI) | 391 | 500 | -| C / C++ | 383 | 330 | -| C# | 337 | 244 | -| Python | 33 | 488 | -| Java | 28 | 175 | -| Go | 24 | 400 | -| WASM | 19 | 167 | -| Node.js | 17 | 10 | -| R | 0.1 | 193 | +| Rust (no FFI) | 380 | 498 | +| C / C++ | 365 | 358 | +| C# | 348 | 259 | +| Python | 31 | 46 | +| Java | 38 | 173 | +| Go | 23 | 394 | +| WASM | 21 | 169 | +| Node.js | 16 | 9 | +| R | 0.1 | 279 | All ten share one verified implementation (see the verification badge above), so the *numbers* differ but the *values* are bit-for-bit identical. Methodology and