Skip to content

Instantly share code, notes, and snippets.

@bjouhier
Last active September 19, 2015 08:31
Show Gist options
  • Save bjouhier/cc188968f124fc995050 to your computer and use it in GitHub Desktop.
Save bjouhier/cc188968f124fc995050 to your computer and use it in GitHub Desktop.
"use strict";
function assert(i, j) {
if (i !== j) throw new Error("expected " + i + ", got " + j)
}
function callbackIter(fn, n, cb) {
var t0 = Date.now();
(function doIt(i) {
if (i < n) fn(i, function(err, val) {
if (err) throw err;
assert(val, 2 * i);
doIt(i + 1);
});
else cb(null, Date.now() - t0);
})(0);
}
function run(fn, iter, cb) {
var threshold = 200;
(function doIt(i) {
iter(fn, i, function(err, val) {
if (err) throw err;
if (val < threshold) {
doIt(2 * i);
} else {
cb(null, Math.floor(i * 1000 / val));
}
});
})(1);
}
var Fiber = require('fibers');
function fiberWrapper(fn) {
return function(i) {
var fiber = Fiber.current;
fn(i, function(err, val) {
if (err) throw err;
fiber.run(val);
});
return Fiber.yield();
}
}
function fiberIterate(fn, n, cb) {
var t0 = Date.now();
Fiber(function() {
for (var i = 0; i < n; i++) {
var val = fn(i);
assert(val, 2 * i);
}
cb(null, Date.now() - t0);
}).run();
}
function fiberCallbackify(fn) {
return function(i, cb) {
Fiber(function() {
fn(i, cb);
}).run();
};
}
function genWrapper(fn) {
return function(i, cb) {
var g = (function *(resume) {
var val = yield fn(i, resume);
cb(null, val);
})(function(err, val) {
if (err) g.throw(err);
else g.next(val);
});
g.next();
};
}
function syncIterate(fn, n, cb) {
var t0 = Date.now();
for (var i = 0; i < n; i++) {
var val = fn(i);
assert(val, 2 * i);
}
var t1 = Date.now();
process.nextTick(function() {
cb(null, t1 - t0);
})
}
function nop(i) {
return 2 * i;
}
function report(prefix, val) {
var s = prefix += ': ';
while (s.length < 24) s += ' ';
s += val + " calls/s";
while (s.length < 48) s += ' ';
s += Math.round(1e9 / val) + ' ns/call';
console.error(s);
}
function runTests(tests, cb) {
var npass = 3;
var skip = 1;
(function doIt(i) {
if (i < tests.length) {
var test = tests[i];
if (!test) {
console.error();
return doIt(i + 1);
}
var sum = 0;
(function pass(j) {
run(test.fn, test.iter, function(err, val) {
if (j > skip) sum += val;
if (j < 3) pass(j + 1);
else {
report(test.name, sum / (npass - skip));
doIt(i + 1);
}
});
})(1);
} else {
cb();
}
})(0);
}
// Test functions
function tickTest(i, cb) {
process.nextTick(function() {
cb(null, 2 * i);
});
}
function immediateTest(i, cb) {
setImmediate(function() {
cb(null, 2 * i);
});
}
function timeoutTest(i, cb) {
setTimeout(function() {
cb(null, 2 * i);
}, 0);
}
var fs = require('fs');
function statTest(i, cb) {
fs.stat(__dirname, function(err, stat) {
if (err) throw err;
assert(stat.isDirectory(), true);
cb(null, 2 * i);
});
}
function statSyncTest(i) {
var stat = fs.statSync(__dirname);
assert(stat.isDirectory(), true);
return 2 * i;
}
runTests([{
name: "sync nop",
iter: syncIterate,
fn: nop,
}, {
name: "fiber nop",
iter: fiberIterate,
fn: nop,
},
null,
{
name: "nextTick cb",
iter: callbackIter,
fn: tickTest,
}, {
name: "nextTick fiber",
iter: fiberIterate,
fn: fiberWrapper(tickTest),
}, {
name: "nextTick fiber cb",
iter: callbackIter,
fn: fiberCallbackify(tickTest),
}, {
name: "nextTick gen",
iter: callbackIter,
fn: genWrapper(tickTest),
},
null,
{
name: "setImmediate cb",
iter: callbackIter,
fn: immediateTest,
}, {
name: "setImmediate fiber",
iter: fiberIterate,
fn: fiberWrapper(immediateTest),
}, {
name: "setImmediate fiber cb",
iter: callbackIter,
fn: fiberCallbackify(immediateTest),
}, {
name: "setImmediate gen",
iter: callbackIter,
fn: genWrapper(immediateTest),
},
null,
{
name: "setTimeout",
iter: callbackIter,
fn: timeoutTest,
}, {
name: "setTimeout fiber",
iter: fiberIterate,
fn: fiberWrapper(timeoutTest),
}, {
name: "setTimeout fiber cb",
iter: callbackIter,
fn: fiberCallbackify(timeoutTest),
}, {
name: "setTimeout gen",
iter: callbackIter,
fn: genWrapper(timeoutTest),
},
null,
{
name: "stat cb",
iter: callbackIter,
fn: statTest,
}, {
name: "stat fiber",
iter: fiberIterate,
fn: fiberWrapper(statTest),
}, {
name: "stat fiber cb",
iter: callbackIter,
fn: fiberCallbackify(statTest),
}, {
name: "stat gen",
iter: callbackIter,
fn: genWrapper(statTest),
}, {
name: "stat sync",
iter: syncIterate,
fn: statSyncTest,
}], function() {
console.error();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment