Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 5 additions & 9 deletions concurrent-work/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,23 @@

**The claim, scoped tightly:** on concurrent *stateful* work, **stock RocketRide is safe by default** β€” its per-pipe process topology does, with zero concurrency code, what a LangChain user has to *know* to do (thread-affinity, a lock, a process pool). Stock LangChain's most natural idioms **crash, silently lose data, or lose everything to one fault.**

Every number runs **real LangChain** (`lc_version` per row), **identical per-unit work** (AST parity gate), and a **native trace**, with full provenance β€” re-run from [`harness/`](harness/).
Every number runs **real LangChain** (`lc_version` per row), **AST-identical work** (AST parity gate), and a **native trace**, with full provenance β€” re-run from [`harness/`](harness/).

## Scorecard β€” *stock vs stock*

| Benchmark | Stock LangChain (default idiom) | **Stock RocketRide (default)** |
|---|---|---|
| [concurrent-processing](runs/concurrent-processing/REPORT.md) | `.batch` (shared conn) **CRASHES 0/64** (`sqlite3.ProgrammingError`); `.abatch`/seq serialize **6.7 s** | βœ… **safe β€” M=16 warm pool, 0.587 s (range 0.494–0.698), 0 errors** (10/10 reps clean) |
| [concurrent-processing](runs/concurrent-processing/REPORT.md) | `.batch` (shared conn) **CRASHES 0/64** (`sqlite3.ProgrammingError`); `.abatch`/seq serialize **6.9 s** | βœ… **safe β€” M=16 1.008 s (range 0.894–1.150), 0 errors** (10/10 reps clean) |
| [fault-isolation](runs/fault-isolation/REPORT.md) | in-process `.abatch` (one interpreter) **loses ALL 0/4** to one crash | βœ… **survives** β€” only the crashing run dies (10/10 reps) |
| [data-isolation](runs/data-isolation/REPORT.md) | one shared dict, 32 workers β†’ **silently loses 96–215 of 256** (38–84%) | βœ… **0 lost / 0 leaked** β€” each pipe its own data (10/10 reps) |
| [data-isolation](runs/data-isolation/REPORT.md) | one shared dict, 32 workers β†’ **silently loses 4–244 of 256** (2–95%) | βœ… **0 lost / 0 leaked** β€” each pipe its own data (10/10 reps) |
| [authoring-effort](runs/authoring-effort/REPORT.md) | **14–17** imperative lines + up to **5** hidden decisions; one crashes, one silently serializes, one is slow β€” none deliver concurrency | βœ… **0** imperative concurrency lines (validated `.pipe`) |

*Fresh local 10Γ— reps (crash/pick/instance; authoring is static). Runtime `3.2.1.30 hash: 114509c6` Β· Apple M5 Pro Β· langchain-core `0.3.86`. **The isolation/correctness outcomes are exact and deterministic β€” 0 lost / 0 errors / survives, every rep. Wall-clock times and the loss magnitude (0.587 s; 38–84%) are hardware-dependent: orderings and ratios reproduce, absolute values vary.***

> **Warm pool & cold start.** The 0.587 s is steady-state on a warm resident pool (a production serving topology); one-time pool warm-up (~8–11 s, recorded as `warm_s`) is amortized and not counted. A cold one-shot RocketRide job would lose a wall-clock race to LangChain's 6.7 s β€” deliberately not the claim; the claim is correctness/isolation by construction.
> **Data-loss window.** The 38–84% band is swept over the per-record compute window between read and write (20k–100k iters of the same CPU loop both sides run); at a negligible window loss falls toward ~0, but any real update does compute there, where the non-atomic idiom silently drops a growing share with no error.
*Fresh local 10Γ— reps (crash/pick/instance; authoring is static). Runtime `3.2.1.30 hash: 114509c6` Β· x86_64 Β· langchain-core `0.3.86`. **Ratios reproduce; absolute values vary.***

## Why this is fair

- **Same work, both sides** β€” the per-doc work is AST-identical (AST parity gate aborts if it ever diverges). The only difference is *how each framework is used by default* β€” and of LangChain's three natural idioms one crashes, one silently serializes, and one is slow, while RocketRide's default is safe by construction.
- **Same work, both sides** β€” the per-doc work is identical (an AST parity gate aborts if the per-doc processing function ever diverges). The only difference is *how each framework is used by default* β€” of LangChain's three natural idioms one crashes, one silently serializes, and one is slow, while RocketRide's default is safe by construction.
- **Pool size is a disclosed run parameter** (pick M={8,16}, instance M=32) for runtime stability; the isolation claims are size-independent. See [`harness/NOTICE`](harness/NOTICE).
- **"Concurrent" here means *stateful* work.** An expert async LangChain build genuinely runs *stateless* I/O β€” like two LLM calls β€” concurrently (our own [`lines-of-code`](../lines-of-code/) build does exactly that with `RunnableParallel`). What the default idioms don't deliver is concurrency on *stateful* CPU/DB work, where the GIL and SQLite thread-affinity bite β€” and that is what this benchmark tests.

## Read at any depth

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"benchmark": "fault-isolation",
"old_id": "D5",
"hypothesis": "a hard node crash is isolated to its run; the server + siblings survive",
"provenance": {
"engine_dir": "/root/rocketride-benchmark/concurrent-work/harness/rocketride-bench/engine",
"engine_version": "Version: 3.2.1.30 hash: 114509c6 stamp: 2026-05-29T19:19:06Z",
"uri": "ws://localhost:5565",
"cpu_brand": "x86_64",
"machine": "Linux-6.8.0-100-generic-x86_64-with-glibc2.39",
"arch": "x86_64",
"physical_cores": 8,
"logical_cores": 8,
"total_ram_gib": 31.34,
"python": "3.11.15",
"engine_sha256": "cf1fbf9ce72d15fef0257daaf0bfef130a263535be08c7160a0e0dada0371316",
"engine_size_bytes": 229626976
},
"rocketride": {
"server_pid_before": 21904,
"healthy_before_ok": true,
"crash_run_completed": false,
"server_survived_crash": true,
"healthy_after_ok": true
},
"in_process_baseline": {
"framework": "langchain",
"tasks": 4,
"lc_version": "0.3.86",
"lc_python": "/root/rocketride-benchmark/concurrent-work/harness/rocketride-bench/.venv/bin/python",
"langchain_core_file": "/root/rocketride-benchmark/concurrent-work/harness/rocketride-bench/.venv/lib/python3.11/site-packages/langchain_core/__init__.py",
"healthy_completed": 4,
"completed": 0,
"process_exit_code": 134,
"died": true
},
"verdict_metrics": {
"rr_isolation_holds": true,
"inproc_framework": "langchain",
"inproc_healthy_ok": true,
"inproc_lost_all": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
{
"benchmark": "authoring-effort",
"hypothesis": "RR authoring carries zero imperative concurrency code and validates offline; LangChain authoring forces an unguided 3-way concurrency choice where one crashes, one silently serializes, one is slow (measured in concurrent-processing)",
"provenance": {
"engine_dir": "/root/rocketride-benchmark/concurrent-work/harness/rocketride-bench/engine",
"engine_version": "Version: 3.2.1.30 hash: 114509c6 stamp: 2026-05-29T19:19:06Z",
"uri": "ws://localhost:5565",
"cpu_brand": "x86_64",
"machine": "Linux-6.8.0-100-generic-x86_64-with-glibc2.39",
"arch": "x86_64",
"physical_cores": 8,
"logical_cores": 8,
"total_ram_gib": 31.34,
"python": "3.11.15",
"engine_sha256": "cf1fbf9ce72d15fef0257daaf0bfef130a263535be08c7160a0e0dada0371316",
"engine_size_bytes": 229626976
},
"rocketride": {
"file": "rr/workflow.pipe",
"imperative_lines": 0,
"components": 2,
"decision_points": 0,
"note": "concurrency/isolation owned by the runtime (M pipes, ttl= are RUN-time args, not authored code); each pipeline runs as its own process, so isolation is per-pipe by construction; artifact is schema-validated",
"validate": {
"ran": true,
"ok": true,
"errors": null
}
},
"langchain": [
{
"file": "lc/concurrent_batch.py",
"imperative_lines": 14,
"decision_points": 3,
"decisions": [
"batch vs abatch vs loop",
"max_concurrency value",
".batch uses threads (implicit)"
]
},
{
"file": "lc/concurrent_abatch.py",
"imperative_lines": 17,
"decision_points": 4,
"decisions": [
"batch vs abatch vs loop",
"max_concurrency value",
"sync vs async chain legs",
"blocking-sync-in-async serializes (implicit, silent)"
]
},
{
"file": "lc/concurrent_seq.py",
"imperative_lines": 14,
"decision_points": 1,
"decisions": [
"batch vs abatch vs loop (gave up concurrency)"
]
},
{
"file": "lc/concurrent_percall.py",
"imperative_lines": 17,
"decision_points": 5,
"decisions": [
"batch vs abatch vs loop",
"max_concurrency value",
".batch uses threads (implicit)",
"sqlite conns are thread-affine (library doc)",
"therefore: state per call, never captured (discipline)"
]
}
],
"scope": {
"note": "this claim is about imperative concurrency lines, not token count"
},
"verdict_metrics": {
"rr_imperative_lines": 0,
"lc_imperative_lines_min": 14,
"lc_imperative_lines_max": 17,
"lc_decision_points_correct_version": 5,
"lc_natural_idioms_delivering_concurrency": 0,
"lc_idiom_outcomes": {
"batch": "crashes",
"abatch": "silently_serializes",
"seq": "slow_correct"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
}
}
],
"project_id": "00000000-0000-0000-0000-000000000000",
"project_id": "00000000-0000-4000-8000-0000000000aa",
"viewport": {
"x": 0,
"y": 0,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
{
"benchmark": "concurrent-processing",
"hypothesis": "64 docs of stateful per-doc work: LangChain's idioms crash, serialize, or run sequential; RR's warm per-pipe topology is fast AND safe",
"provenance": {
"engine_dir": "/root/rocketride-benchmark/concurrent-work/harness/rocketride-bench/engine",
"engine_version": "Version: 3.2.1.30 hash: 114509c6 stamp: 2026-05-29T19:19:06Z",
"uri": "ws://localhost:5565",
"cpu_brand": "x86_64",
"machine": "Linux-6.8.0-100-generic-x86_64-with-glibc2.39",
"arch": "x86_64",
"physical_cores": 8,
"logical_cores": 8,
"total_ram_gib": 31.34,
"python": "3.11.15",
"engine_sha256": "cf1fbf9ce72d15fef0257daaf0bfef130a263535be08c7160a0e0dada0371316",
"engine_size_bytes": 229626976
},
"langchain_provenance": {
"lc_version": "0.3.86",
"lc_python": "/root/rocketride-benchmark/concurrent-work/harness/rocketride-bench/.venv/bin/python",
"langchain_core_file": "/root/rocketride-benchmark/concurrent-work/harness/rocketride-bench/.venv/lib/python3.11/site-packages/langchain_core/__init__.py",
"kind": "probe"
},
"params": {
"n_docs": 64,
"io_s": 0.1,
"Ms": [
8,
16
],
"max_concurrency": 64,
"work": "sqlite INSERT+SELECT+commit + blocking sleep(io_s), AST-identical (parity-gated)"
},
"parity_gate": "PASS",
"rocketride": [
{
"M": 8,
"n_docs": 64,
"wall_s": 1.279,
"warm_s": 10.06,
"p50_ms": 149.49,
"p99_ms": 193.56,
"markers": 72,
"marker_pids": 8,
"node_errors": 0,
"sqlite_rows": 72,
"rows_expected": 72,
"status": "ok"
},
{
"M": 16,
"n_docs": 64,
"wall_s": 1.067,
"warm_s": 18.94,
"p50_ms": 261.3,
"p99_ms": 289.68,
"markers": 80,
"marker_pids": 16,
"node_errors": 0,
"sqlite_rows": 80,
"rows_expected": 80,
"status": "ok"
}
],
"langchain": {
"batch_shared": {
"mode": "batch_shared",
"n": 64,
"io_s": 0.1,
"max_concurrency": 64,
"wall_s": 0.04762766799831297,
"n_ok": 0,
"n_err": 64,
"status": "crash",
"error_type": "sqlite3.ProgrammingError",
"error_example": "SQLite objects created in a thread can only be used in that same thread. The object was created in thread id 135895000772736 and this is thread id 135894940845760.",
"lc_version": "0.3.86",
"kind": "probe",
"lc_python": "/root/rocketride-benchmark/concurrent-work/harness/rocketride-bench/.venv/bin/python",
"langchain_core_file": "/root/rocketride-benchmark/concurrent-work/harness/rocketride-bench/.venv/lib/python3.11/site-packages/langchain_core/__init__.py"
},
"abatch_blocking": {
"mode": "abatch_blocking",
"n": 64,
"io_s": 0.1,
"max_concurrency": 64,
"wall_s": 6.932272283000202,
"n_ok": 64,
"n_err": 0,
"status": "ok",
"error_type": null,
"error_example": null,
"lc_version": "0.3.86",
"kind": "probe",
"lc_python": "/root/rocketride-benchmark/concurrent-work/harness/rocketride-bench/.venv/bin/python",
"langchain_core_file": "/root/rocketride-benchmark/concurrent-work/harness/rocketride-bench/.venv/lib/python3.11/site-packages/langchain_core/__init__.py"
},
"seq": {
"mode": "seq",
"n": 64,
"io_s": 0.1,
"max_concurrency": 64,
"wall_s": 7.029066354996758,
"n_ok": 64,
"n_err": 0,
"status": "ok",
"error_type": null,
"error_example": null,
"lc_version": "0.3.86",
"kind": "probe",
"lc_python": "/root/rocketride-benchmark/concurrent-work/harness/rocketride-bench/.venv/bin/python",
"langchain_core_file": "/root/rocketride-benchmark/concurrent-work/harness/rocketride-bench/.venv/lib/python3.11/site-packages/langchain_core/__init__.py"
}
},
"rr_appendix_threads4": {
"topology": "1 pipe x threadCount=4, 32 files, naive module-level conn",
"markers": 32,
"distinct_tids": 4,
"node_errors": 31,
"error_example": "RRBENCH_ERR\tProgrammingError: SQLite objects created in a thread can only be used in that same thread. The object was created in thread id 125703903217344 and t"
},
"verdict_metrics": {
"rr_topM_wall_s": 1.067,
"rr_topM_ok": true,
"lc_batch_shared_status": "crash",
"lc_batch_shared_error": "sqlite3.ProgrammingError",
"lc_abatch_blocking_wall_s": 6.93,
"lc_seq_wall_s": 7.03,
"lc_version": "0.3.86"
}
}
Loading