How V8 Optimizes Async/Await: Performance Boosts from Node 8 to 12
This article explains how V8’s compiler, garbage collector, and a bug‑inspired optimization improve async/await performance across Node.js versions, detailing benchmark results, code behavior differences, and the engine’s internal steps for handling await.
Async Introduction
Async functions use an implicit Promise to perform asynchronous operations and return their result, making asynchronous code appear synchronous, simplifying syntax, and allowing try/catch for error handling.
Async performance across Node versions
The benchmark shows that lower execution time means better performance; V8 noticeably improved async code speed from v5.5 to v6.8.
Reasons for performance improvement
Overall gains stem from three areas:
New optimizing compiler TurboFan
New garbage collector Orinoco
An optimization inspired by the Node 8 await bug
const p = Promise.resolve();
(async () => {
await p;
console.log('after:await');
})();
p.then(() => console.log('tick:a')).then(() => console.log('tick:b'));In Node 8 the output order is "after:await" then the two "tick" logs, but Node 10 follows the specification and prints the two "tick" logs before "after:await" because the earlier behavior was a bug.
V8’s handling of await follows these steps for a simple async function async function foo(v) { const w = await v; return w; }:
async function foo(v) {
const w = await v;
return w;
}Mark the function as resumable (it can pause and later resume).
Create an implicit Promise that will be returned to the caller.
Convert the argument v to a Promise, wrapping it if it isn’t already one.
Attach handlers to the Promise so the function can resume later.
Suspend the async function and return the implicit Promise.
When the Promise fulfills, resume execution, assign its value to w, and continue.
Even when v is already a Promise, V8 originally created an extra wrapper, adding overhead. The newer optimization skips this extra wrapper, saving a Promise allocation and two micro‑task ticks, which both improves performance and restores the Node 8 logging order while remaining spec‑compliant. This optimization is enabled by default starting with Node.js 12.
Node Underground
No language is immortal—Node.js isn’t either—but thoughtful reflection is priceless. This underground community for Node.js enthusiasts was started by Taobao’s Front‑End Team (FED) to share our original insights and viewpoints from working with Node.js. Follow us. BTW, we’re hiring.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
