Benchmarking & Optimization for fun and profit!!
@AhmadNassri
AhmadNassri.com
Principal Architect at TELUS Digital, Founder at Bench CI, Founder at Tech Masters, Mentor at Node School Toronto, Board Member at Full Stack Toronto, Editor at The RESTful Web.
Tech Outlaw, Wanted by a third-world dictator
(true story)
&
Code quality is not enough, keep track of performance and efficient resource usage.
Memory capacity & CPU cycles are precious in resource constrained environments
Ensure your software operates on and within any hardware & resource constraints.
A Bank System manages a trillion dollars, processes millions of transactions per minute.
You are the best coder in the world, your error rate is 0.001.
Will your change save us a billion dollars or cost us billions?
Discover optimizations that could impact the largest number of users
$ time for a in {1..10}; do node bench.js; done
real 0m13.042s
user 0m0.021s
sys 0m0.044shttps://benchmarkjs.com
new Benchmark.Suite()
.add({
name: 'JSON.parse',
fn: () => JSON.parse(json)
})
.add({
name: 'jsonparse',
defer: true,
fn: (deferred) => {
let p = new Jsonparse()
p.onValue = function (data) {
if (this.stack.length === 0) {
deferred.resolve()
}
}
p.write(json)
}
})
.add({
name: 'vuvuzela',
fn: () => vuvuzela.parse(json)
})
.run() clarinet x 2,636 ops/sec ±2.13% (78 runs sampled)
JSON.parse x 80,639 ops/sec ±2.14% (88 runs sampled)
jju x 7,343 ops/sec ±3.12% (84 runs sampled)
jsonparse x 10,719 ops/sec ±4.54% (45 runs sampled)
json-parse-stream x 2,039 ops/sec ±6.39% (69 runs sampled)
stream-json x 1,775 ops/sec ±1.14% (82 runs sampled)
vuvuzela x 15,644 ops/sec ±4.07% (87 runs sampled)https://github.com/ahmadnassri/benchmark-node-json-parse
https://github.com/ahmadnassri/benchmark-node-clone
app.get('/auth', function (req, res) {
var username = req.query.username || '';
var password = req.query.password || '';
username = username.replace(/[!@#$%^&*]/g, '');
if (!username || !password || !users[username]) {
return res.sendStatus(400);
}
var hash = crypto.pbkdf2Sync(password, users[username].salt, 10000, 512);
if (users[username].hash.toString() === hash.toString()) {
res.sendStatus(200);
} else {
res.sendStatus(401);
}
});node --prof ./app.js
node --prof-process ./the-generated-log-file[Summary]:
ticks total nonlib name
79 0.2% 0.2% JavaScript
36703 97.2% 99.2% C++
7 0.0% 0.0% GC
767 2.0% Shared libraries
215 0.6% Unaccounted [C++]:
ticks total nonlib name
19557 51.8% 52.9% node::crypto::PBKDF2(v8::FunctionCallbackInfo<v8::Value> const&)
4510 11.9% 12.2% _sha1_block_data_order
3165 8.4% 8.6% _malloc_zone_malloc [Bottom up (heavy) profile]
ticks parent name
19557 51.8% node::crypto::PBKDF2(v8::FunctionCallbackInfo<v8::Value> const&)
19557 100.0% v8::internal::Builtins::~Builtins()
19557 100.0% LazyCompile: ~pbkdf2 crypto.js:557:16
4510 11.9% _sha1_block_data_order
4510 100.0% LazyCompile: *pbkdf2 crypto.js:557:16
4510 100.0% LazyCompile: *exports.pbkdf2Sync crypto.js:552:30
3165 8.4% _malloc_zone_malloc
3161 99.9% LazyCompile: *pbkdf2 crypto.js:557:16
3161 100.0% LazyCompile: *exports.pbkdf2Sync crypto.js:552:30app.get('/auth', function (req, res) {
var username = req.query.username || '';
var password = req.query.password || '';
username = username.replace(/[!@#$%^&*]/g, '');
if (!username || !password || !users[username]) {
return res.sendStatus(400);
}
crypto.pbkdf2(password, users[username].salt, 10000, 512, function(err, hash) {
if (users[username].hash.toString() === hash.toString()) {
res.sendStatus(200);
} else {
res.sendStatus(401);
}
})
})@AhmadNassri
AhmadNassri.com
Slides & Links will be up on
AhmadNassri.com/talks
TechMasters.chat
NodeSchool.io/toronto
FSTO.co