Performance of v8 generators vs promises

Measuring generator vs promise performance.

I showed several solutions to computing factorial using asynchronous methods in Factorial using promises. Two of the solutions used native ES6 promises and generators. I wanted to find out which one is faster.

Setup

Chrome v8 natively supports both features. I started with a simple page and performance profile calls.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<title>generators vs promises</title>
<script src="generators-factorial.js"></script>
<script src="native-promises.js"></script>
</head>
<body>
<h2>Profiling factorial functions</h2>
<script>
var large = 100000;
// sync solution using generators
console.profile('generators-factorial');
factorial(large);
console.profileEnd('generators-factorial');
// async solution using promises
console.profile('native-promises');
factorialPromises(large).then(function () {
console.profileEnd('native-promises');
});
</script>
</body>
</html>

Here are the two solutions

generators-factorial.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function* Factorial() {
var n = 1, total = 1;
while (true) {
total = total * n++;
yield total;
};
}
function factorial(n) {
var f = Factorial(), k, nf;
for (k = 0; k < n; k += 1) {
nf = f.next().value;
}
return nf;
}
// native-promises.js
function valuePromise(n) {
return new Promise(function (resolve) {
return resolve(n);
});
}
function factorialPromises(n) {
var start = valuePromise(n);
while (n -= 1) {
start = start.then(function (n, value) {
// console.log('n', n, 'value', value)
return value * n;
}.bind(null, n));
}
return start;
}

Performance profile

Open this page in Chrome (I have v40) and be surprised by the huge difference in performance. The solution using promises takes 1 second.

promises

The solution using generator function takes 7 milliseconds.

generator

JsPerf

I was so surprised by this difference that I wanted another confirmation. I posted the same code to jsperf website and ran the tests on Chrome, Chrome Canary and Firefox. The results confirmed that using a single generator function is much much faster than creating a long chain of promises and executing a large number of .then callbacks.

jsperf

You can run the test yourself at jsperf.com/v8-generators-vs-promises

Conclusion

Promises are powerful, but there is a performance penalty to using them. There are ways to use generators AND promises together to minimize the penalty, see Going Async With ES6 Generators by Kyle Simpson.