V8 Engine's Mutable Heap Numbers Boost JavaScript Performance by 2.5x in Key Benchmark

By • min read

Breaking: V8 Optimization Yields 2.5x Speedup in async-fs Benchmark

The V8 team at Google has announced a major optimization that delivers a 2.5x performance improvement in the JetStream2 async-fs benchmark. The breakthrough comes from converting immutable heap numbers to mutable ones, eliminating a critical bottleneck in JavaScript's Math.random implementation.

V8 Engine's Mutable Heap Numbers Boost JavaScript Performance by 2.5x in Key Benchmark
Source: v8.dev

'This optimization was inspired by the benchmark, but such patterns do appear in real-world code,' a V8 engineer explained. The fix addresses a surprising performance issue hidden in the custom Math.random used for deterministic testing.

Background: The HeapNumber Allocation Bottleneck

The async-fs benchmark implements a JavaScript file system and uses a custom Math.random function for consistency. The seed variable, updated on every call, is stored in a ScriptContext—an array of tagged values on 64-bit systems.

V8 uses a tagging scheme: a 0-bit indicates a Small Integer (SMI) stored directly, while a 1-bit indicates a pointer to a heap object. The seed variable's slot pointed to an immutable HeapNumber on the heap—a 64-bit double-precision floating-point value. Each update to seed forced allocation of a new HeapNumber object, causing significant performance overhead.

Profiling revealed two major issues: frequent heap allocations and the overhead of creating new HeapNumbers. 'The allocation was a major performance cliff,' another V8 developer noted. 'We needed a way to update the number in place.'

The Optimization: Mutable Heap Numbers

The team introduced a new mutable HeapNumber variant that allows in-place updates. Instead of allocating a new object on each Math.random call, the seed value is stored in a mutable heap slot that can be directly modified. This eliminates the allocation bottleneck and reduces garbage collection pressure.

The change was implemented in V8's JSTypedArray and ScriptContext handling. 'By making the heap number mutable, we cut out the repeated allocation entirely,' said a performance engineer. 'The result was a 2.5x speedup in the targeted benchmark and a notable lift in the overall JetStream2 score.'

What This Means for JavaScript Developers

While the optimization was triggered by a benchmark, similar patterns occur in real-world applications—particularly in simulations, games, or any code using repeatedly updated numeric values stored in context slots. Developers can expect faster execution for tasks that rely on mutable state in closures or module-level variables.

'This isn't just about Math.random,' the team emphasized. 'Any JavaScript code that updates a number stored in a script context will benefit from this optimization.' The fix is already included in recent V8 releases, and Chrome users will see the improvement automatically.

Broader Implications for JavaScript Engines

The V8 team's approach demonstrates that heap number mutability can be safely introduced without breaking JavaScript's value semantics. Future optimizations may extend mutable heap numbers to other contexts, such as object properties and arrays, potentially yielding further performance gains.

Editors Note: This optimization is part of ongoing V8 efforts to eliminate performance cliffs in the JetStream2 suite. The async-fs benchmark improvement is one of several planned enhancements for 2024.

Recommended

Discover More

From Lab Marvels to Real-World Tools: The Hard Path for Bionic TechnologyUnderstanding and Defending Against Supply Chain Attacks: A Daemon Tools Case StudyThe Hidden Reversal: How Climate Change Transforms Winter LakesUnlocking Legacy Applications for AI Agents: Amazon WorkSpaces Introduces Dedicated Desktop Environments (Preview)How to Detect and Recover from a GitHub Actions Compromise Targeting PyPI Packages