Performance test of async / await in Node.js 8 LTS
The recently released Node.js 8 LTS comes with async
/ await
support, which turns promises from an ugly kludge into something actually useful.
This post shows an example of using the new async
/ await
feature and compares performance to a traditional callback implementation.
TL;DR
When tested against an HTTP server running on localhost the promises implementation was about 2% slower, which is, for the most part, negligible.
Benchmark
The test scenario involves making three HTTP requests in sequence, using the result of the previous request as the path for the next one. This is a simplified version of a standard real-life use-case of assembling some data from several different API endpoints.
Callback version
const http = require('http');
function makeRequest (path, callback) {
const o = {
method: 'GET',
port: 8080,
path: path
};
const req = http.request(o, (res) => {
const data = [];
res.on('data', (buffer) => {
data.push(buffer);
});
res.on('end', () => {
callback(undefined, Buffer.concat(data).toString());
});
});
req.on('error', (err) => {
callback(err);
});
req.end();
}
function getData (callback) {
makeRequest('/a', (err, path1) => {
if (err) {
return callback(err);
}
makeRequest(path1, (err, path2) => {
if (err) {
return callback(err);
}
makeRequest(path2, (err, path3) => {
if (err) {
return callback(err);
}
callback(undefined, path3);
});
});
});
}
Promise version
const http = require('http');
function makeRequest(path) {
return new Promise((resolve, reject) => {
const o = {
method: 'GET',
port: 8080,
path: path
};
const req = http.request(o, (res) => {
const data = [];
res.on('data', (buffer) => {
data.push(buffer);
});
res.on('end', () => {
resolve(Buffer.concat(data).toString());
});
});
req.on('error', (err) => {
reject(err);
});
req.end();
});
}
async function getData (callback) {
let path;
try {
path = await makeRequest('/a');
path = await makeRequest(path);
path = await makeRequest(path);
} catch (e) {
callback(e);
}
callback(undefined, path);
}
Benchmark code
const results = [];
(function loop (i) {
if (i) {
let start = Date.now();
getData((err) => {
if (err) {
throw err;
}
results.push(Date.now() - start);
process.nextTick(() => {
loop(i - 1);
});
});
} else {
console.log(results.slice(10).reduce((sum, n) => {
return sum + n;
}, 0));
}
}(100010));
HTTP server code
var http = require('http');
const server = http.createServer((req, res) => {
if (req.url === '/a') {
res.end('/b');
} else if (req.url === '/b') {
res.end('/c');
} else if (req.url === '/c') {
res.end('/d');
}
});
server.listen(8080);
Results
Node version 8.9.1 was used in this test.
Callback version
51616
51504
52370
51137
51477
51574
51818
51019
51053
51458
Avg: 51502.6
Promise version
52701
52447
52264
52816
52913
52637
52104
52659
52193
52330
Avg: 52506.4