← Back to Architecture & Comparison Guides
Published: 2026-10-23 Updated: 2026-10-23 Source: bend2.org

Bend 2 vs. JavaScript (Node.js, Bun, V8): Single-Threaded Event Loops vs. Lock-Free Interaction Parallelism

An execution-level comparison of JavaScript (V8, JavaScriptCore, Web Workers, SharedArrayBuffer) and Bend 2 (BendRT Task Cube and zero-dependency JS target) across 16 Apple M4 Max benchmarks.


Executive Summary: Bottom Line Up Front

JavaScript engines (Google V8 in Node.js/Deno and JavaScriptCore in Bun) excel at single-threaded Just-In-Time (JIT) compilation and asynchronous I/O, but their shared-nothing isolate architecture makes fine-grained multi-core and GPU parallelism expensive.

  1. Keep JavaScript (Node.js, Bun, Browser DOM) for event-driven HTTP/WebSocket servers, SSR rendering, browser interactivity, and single-threaded workloads dominated by flat hash-map lookups (Map, object property inline caches).
  2. Use Bend 2 (bend -o native binary or GPU kernel) whenever a CPU-bound or recursive computation blocks the JavaScript event loop. Spawning worker_threads or Web Workers in JavaScript forces recursive trees and object graphs through structuredClone serialization. By contrast, Bend 2’s BendRT Task Cube distributes 64-bit tasks across 16 CPU cores (PAR-CPU) and 16,384 GPU lanes (PAR-GPU) with zero serialization, zero locks, and zero garbage collection pauses (bendlang/bend). Across the 16 Apple M4 Max benchmarks, Bend 2’s 16-core CPU runtime outruns V8/Bun by 3.75x to 65.13x, and its GPU runtime outruns V8/Bun by up to 297.68x (benchmark dataset).
  3. Use Bend 2’s JavaScript Target (bend prog.bend -o prog.js) when you want to ship mathematically proven, termination-checked algorithms (LAWS.bend / PROOF.bend) into browsers, Cloudflare Workers, or Node/Bun services with zero npm dependencies (bendlang/bend).

1. The JavaScript Concurrency Wall: Event Loop Blocking & structuredClone Overhead

Why does JavaScript struggle on parallel tree, graph, and simulation algorithms? The bottleneck is architectural:

1.1 One Thread Per Isolate

Every V8 or JavaScriptCore isolate runs user JavaScript on a single execution thread. If a request handler runs a 500 ms tree search, raytrace, or K-means clustering pass, the entire event loop stalls. That stall starves every concurrent HTTP socket, timer, and promise microtask in that process.

1.2 Why worker_threads and Web Workers Fail on Recursive Trees

To use multiple CPU cores in Node.js or Bun, developers must spawn worker_threads or Web Workers. Because each worker owns an isolated V8/JSC heap, passing a recursive data structure (such as an AST, Merkle tree, or BVH scene graph) between workers invokes the Structured Clone Algorithm (structuredClone / postMessage):

1.3 How BendRT Eliminates Both Serialization and Locks

In Bend 2, a parallel let binding (a b = f(x) g(y)) executes inside a single unified 8 TiB virtual address space (MAP_NORESERVE) shared across all CPU threads and unified-memory GPU warps (bendlang/bend):


2. Empirical Benchmarks: V8/Bun vs. Bend 2 on Apple M4 Max

The table below compares JavaScript/TypeScript execution on V8/Bun (ts_sec) against Bend 2’s sequential CPU (SEQ-CPU), 16-core parallel CPU (PAR-CPU), and Metal GPU (PAR-GPU) runtimes across 10 representative workloads from /data/bend-ecosystem.json (benchmark dataset):

Workload Category JS / TS (V8/Bun) Bend SEQ-CPU (RSS) Bend PAR-CPU 16c (RSS) Bend PAR-GPU Metal PAR-CPU Speedup vs. JS PAR-GPU Speedup vs. JS
Conway’s Game of Life Cellular Automata 18.754 s 7.803 s (2.1 MB) 0.647 s (2.7 MB) 0.063 s 28.99x 297.68x (source)
3D Raytracer Computer Graphics 23.039 s 4.616 s (2.1 MB) 0.396 s (2.6 MB) 0.151 s 58.18x 152.58x (source)
Merkle Tree Cryptographic Trees 7.227 s 4.222 s (130 MB) 0.422 s (131 MB) 0.071 s 17.13x 101.79x (source)
K-Means Clustering Machine Learning 17.455 s 2.069 s (23.5 MB) 0.268 s (24.1 MB) 0.191 s 65.13x 91.39x (source)
N-Body Physics Particle Gravity 5.332 s 5.758 s (2.2 MB) 0.516 s (2.7 MB) 0.059 s 10.33x 90.37x (source)
Tree Bitonic Sort Sorting Networks 33.910 s 6.043 s (146 MB) 0.799 s (156 MB) 0.450 s 42.44x 75.36x (source)
Mandelbrot Fractal Complex Plane 3.837 s 4.473 s (2.3 MB) 0.395 s (2.9 MB) 0.057 s 9.71x 67.32x (source)
Tree Matrix Multiply Quadtree Algebra 11.379 s 2.064 s (2.8 MB) 0.226 s (14.8 MB) 0.231 s 50.35x 49.26x (source)
Regex Parallel Lexer Text Processing 3.543 s 2.144 s (2.0 MB) 0.198 s (3.0 MB) 1.075 s 17.89x 3.30x (source)
HAMT Hashmap Data Structures 0.892 s 2.741 s (2.4 MB) 0.238 s (9.0 MB) 0.521 s 3.75x 1.71x (source)

Honest Analysis: Where V8 Beats Sequential Bend (nbody, mandelbrot, hashmap)

Look closely at the JS / TS vs. Bend SEQ-CPU columns in the table above (benchmark dataset):


3. Inside Bend 2’s JavaScript Compiler Target (bend -o prog.js)

In addition to compiling to native C/CUDA/Metal (bend prog.bend -o prog), Bend 2 includes a first-class JavaScript code generator (js_book and js_lib in bend2/comp.ts) (bendlang/bend):

# Emit a standalone executable JS file
bend src/engine.bend -o dist/engine.js

# Emit an ES module for import in Node.js, Bun, or Browser bundles
bend src/engine.bend -o dist/engine.mjs

How Bend 2 Values Map to Native JavaScript

The generated JavaScript has zero external runtime dependencies and maps BendTT types directly onto fast V8/JSC primitives (bendlang/bend):

Bend 2 Construct Emitted JavaScript Representation Runtime Characteristics
Algebraic Constructors (Succ{pred}) Plain objects: {$: "Succ", pred} Monomorphic object shapes optimize cleanly in V8 hidden classes (source)
Natural Numbers (Nat) Native JavaScript BigInt (0n, 1n, capped at 248 − 1) Exact arbitrary-precision integer arithmetic without float rounding (source)
Machine Scalars (U32, F32) (x >>> 0) unsigned 32-bit ints and Math.fround(x) Unboxed SMI / double representation in V8 and JSC (source)
Linear Array<T> Native JS Array ([]) with in-place index assignment Zero-copy array mutation verified safe by BendTT’s affine checker (source)
Tail-Recursive Functions Trampolined while loop (run_loop) Prevents RangeError: Maximum call stack size exceeded on deep recursion (source)

4. When to Choose JavaScript vs. Bend 2

Engineering Scenario Recommended Choice Why
HTTP APIs, WebSockets, DOM UI, Edge Routing JavaScript (Node / Bun) Non-blocking epoll/kqueue event loop and universal web ecosystem.
Multi-Core / GPU Tree, Graph, Physics, or Sorting Kernel Bend 2 (bend -o Native / GPU) Up to 297.68x faster than V8 without worker_threads or structuredClone overhead (source).
Browser or Edge Module Requiring Mathematical Correctness Bend 2 (bend -o module.mjs) Prove invariants in 0.38 s via LAWS.bend/PROOF.bend, then ship zero-dependency JS (source).
High-Density CLI / Pre-Commit Hook / Agent Swarm Gate Bend 2 (bend -o Native) 3.11 ms startup and 2.66 MB RSS vs. 45 to 60 MB RSS for Node.js scripts (source).