Last active
December 17, 2015 08:39
-
-
Save gmalysa/5581882 to your computer and use it in GitHub Desktop.
Quick benchmark test for comparing flux-link to some standard async packages that are commonly used
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Results: | |
Promise overhead (calling one after another) x1000: | |
1: 65ms Base (plain Node.js lstat call) | |
2: 75ms When: Dedicated wrapper | |
3: 86ms flux-link | |
4: 97ms Deferred: Dedicated wrapper | |
5: 102ms Deferred: Promisify (generic wrapper) | |
6: 135ms jQuery.Deferred: Dedicated wrapper | |
7: 1055ms Q: Dedicated wrapper | |
8: 1538ms Q: nbind (generic wrapper) | |
Source code is based on https://github.com/medikoo/deferred/blob/master/benchmark/one-after-another.js, | |
modified to include a test for flux-link. Tests were run on an amazon EC2 micro instance (hence the short | |
duration to avoid cpu throttling). Repeated tests show that there is not much total difference between | |
deferred, when, and flux-link, with the order changing from time to time and run times varying from | |
70-120 ms for each. If you want/can re-run on a server that does not have throttling concerns to do tests | |
of a longer duration, that'd be great. | |
'use strict'; | |
// Benchmark comparing overhead introduced by promise implementations | |
// (one by after another) | |
// To run it, do following in package path: | |
// | |
// $ npm install Q jquery when flux-link | |
// $ node benchmark/one-after-another.js | |
var forEach = require('es5-ext/lib/Object/for-each') | |
, pad = require('es5-ext/lib/String/prototype/pad') | |
, lstat = require('fs').lstat | |
, Q = require('Q') | |
, jqDeferred = require('jquery').Deferred | |
, when = require('when') | |
, deferred = require('../lib') | |
, fl = require('flux-link') | |
, now = Date.now | |
, Deferred = deferred.Deferred, promisify = deferred.promisify | |
, nextTick = process.nextTick | |
, self, time, count = 1000, data = {}, next, tests, def = deferred(); | |
console.log("Promise overhead (calling one after another)", | |
"x" + count + ":\n"); | |
tests = [function () { | |
var i = count; | |
self = function () { | |
lstat(__filename, function (err, stats) { | |
if (err) { | |
throw err; | |
} | |
if (--i) { | |
self(stats); | |
} else { | |
data["Base (plain Node.js lstat call)"] = now() - time; | |
next(); | |
} | |
}); | |
}; | |
time = now(); | |
self(); | |
}, function () { | |
var i = count, dlstat; | |
dlstat = function (path) { | |
var def = new Deferred(); | |
lstat(path, function (err, stats) { | |
def.resolve(err || stats); | |
}); | |
return def.promise; | |
}; | |
self = function () { | |
dlstat(__filename).end(function (stats) { | |
if (--i) { | |
self(stats); | |
} else { | |
data["Deferred: Dedicated wrapper"] = now() - time; | |
next(); | |
} | |
}); | |
}; | |
time = now(); | |
self(); | |
}, function () { | |
var i = count, dlstat = promisify(lstat); | |
self = function () { | |
dlstat(__filename).end(function (stats) { | |
if (--i) { | |
self(stats); | |
} else { | |
data["Deferred: Promisify (generic wrapper)"] = now() - time; | |
next(); | |
} | |
}); | |
}; | |
time = now(); | |
self(); | |
}, function () { | |
var i = count, dlstat; | |
dlstat = function (path) { | |
var def = Q.defer(); | |
lstat(path, function (err, stats) { | |
if (err) { | |
def.reject(err); | |
} else { | |
def.resolve(stats); | |
} | |
}); | |
return def.promise; | |
}; | |
self = function () { | |
dlstat(__filename).then(function (stats) { | |
if (--i) { | |
self(stats); | |
} else { | |
data["Q: Dedicated wrapper"] = now() - time; | |
// Get out of try/catch clause | |
nextTick(next); | |
} | |
}).done(); | |
}; | |
time = now(); | |
self(); | |
}, function () { | |
var i = count, dlstat = Q.nbind(lstat, null); | |
self = function () { | |
dlstat(__filename).then(function (stats) { | |
if (--i) { | |
self(stats); | |
} else { | |
data["Q: nbind (generic wrapper)"] = now() - time; | |
// Get out of try/catch clause | |
nextTick(next); | |
} | |
}).done(); | |
}; | |
time = now(); | |
self(); | |
}, function () { | |
var i = count, dlstat; | |
dlstat = function (path) { | |
var def = jqDeferred(); | |
lstat(path, function (err, stats) { | |
if (err) { | |
def.reject(err); | |
} else { | |
def.resolve(stats); | |
} | |
}); | |
return def; | |
}; | |
self = function () { | |
dlstat(__filename).done(function (stats) { | |
if (--i) { | |
self(stats); | |
} else { | |
data["jQuery.Deferred: Dedicated wrapper"] = now() - time; | |
next(); | |
} | |
}).fail(function (e) { | |
throw e; | |
}); | |
}; | |
time = now(); | |
self(); | |
}, function () { | |
var i = count, dlstat; | |
dlstat = function (path) { | |
var def = when.defer(); | |
lstat(path, function (err, stats) { | |
if (err) { | |
def.reject(err); | |
} else { | |
def.resolve(stats); | |
} | |
}); | |
return def.promise; | |
}; | |
self = function () { | |
dlstat(__filename).then(function (stats) { | |
if (--i) { | |
self(stats); | |
} else { | |
data["When: Dedicated wrapper"] = now() - time; | |
nextTick(next); | |
} | |
}, function (e) { | |
nextTick(function () { | |
throw e; | |
}); | |
}); | |
}; | |
time = now(); | |
self(); | |
}, function() { | |
var i = count, env; | |
var chain = new fl.Chain(); | |
function dlstat(env, after, stats) { | |
// $check does the same error checking on the first argument and only passes the remaining | |
// arguments if it is false-like, otherwise an exception is thrown | |
lstat(env.path, env.$check(after)); | |
}; | |
for (i = count; i > 0; --i) { | |
chain.push(dlstat); | |
} | |
env = new fl.Environment({}, console.log); | |
time = now(); | |
env.path = __filename; | |
chain.call(null, env, function() { | |
data["flux-link"] = now() - time; | |
nextTick(next); | |
}, {}); | |
}]; | |
next = function () { | |
if (tests.length) { | |
tests.shift()(); | |
} else { | |
def.resolve(); | |
forEach(data, function (value, name, obj, index) { | |
console.log(index + 1 + ":", pad.call(value, " ", 5) + "ms ", name); | |
}, null, function (a, b) { | |
return this[a] - this[b]; | |
}); | |
} | |
}; | |
next(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment