jsPerf.app is an online JavaScript performance benchmark test runner & jsperf.com mirror. It is a complete rewrite in homage to the once excellent jsperf.com now with hopefully a more modern & maintainable codebase.
jsperf.com URLs are mirrored at the same path, e.g:
https://jsperf.com/negative-modulo/2
Can be accessed at:
https://jsperf.app/negative-modulo/2
Added groxx pubsub.js ( which supports namespacing )
https://raw.github.com/Groxx/PubSub/
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js">
</script>
<script>
;
(function(d) {
// the topic/subscription hash
var cache = {};
d.publish1 = function( /* String */ topic, /* Array? */ args) {
cache[topic] && d.each(cache[topic], function() {
this.apply(d, args || []);
});
};
d.subscribe1 = function( /* String */ topic, /* Function */ callback) {
if (!cache[topic]) {
cache[topic] = [];
}
cache[topic].push(callback);
return [topic, callback]; // Array
};
d.unsubscribe1 = function( /* Array */ handle) {
var t = handle[0];
cache[t] && d.each(cache[t], function(idx) {
if (this == handle[1]) {
cache[t].splice(idx, 1);
}
});
};
})(jQuery);
/* jQuery Tiny Pub/Sub - v0.7 - 10/27/2011
* http://benalman.com/
* Copyright (c) 2011 "Cowboy" Ben Alman; Licensed MIT, GPL */
(function($) {
var o = $({});
$.subscribe2 = function() {
o.on.apply(o, arguments);
};
$.unsubscribe2 = function() {
o.off.apply(o, arguments);
};
$.publish2 = function() {
o.trigger.apply(o, arguments);
};
}(jQuery));
/*
* Simple Pub/Sub Implementation for jQuery
*
* Inspired by work from Peter Higgins (https://github.com/phiggins42/bloody-jquery-plugins/blob/master/pubsub.js)
*
* This is about the simplest way to write a pubsub JavaScript implementation for use with jQuery.
*/
(function($) {
// Cache of all topics
var topics = {};
// Iterates through all subscribers of a topic and invokes their callback,
// passing optional arguments.
$.publish3 = function(topic, args) {
if (topics[topic]) {
var thisTopic = topics[topic],
thisArgs = args || [];
for (var i = 0, j = thisTopic.length; i < j; i++) {
thisTopic[i].apply($, thisArgs);
}
}
};
// Returns a handle needed for unsubscribing
$.subscribe3 = function(topic, callback) {
if (!topics[topic]) {
topics[topic] = [];
}
topics[topic].push(callback);
return {
topic: topic,
callback: callback
};
};
// Removes the subscriber from the particular topic its handle was assigned to
$.unsubscribe3 = function(handle) {
var topic = handle.topic;
if (topics[topic]) {
var thisTopic = topics[topic];
for (var i = 0, j = thisTopic.length; i < j; i++) {
if (thisTopic[i] === handle.callback) {
thisTopic.splice(i, 1);
// break; here? duplicate handles are possible
}
}
}
};
})(jQuery);
(function(d) {
var cache = {};
d.publish4 = function(topic, args) {
if (cache[topic]) {
var currentCache = cache[topic],
currentArgs = args || [];
for (var i = 0, j = currentCache.length; i < j; i++) {
currentCache[i].apply(d, currentArgs);
}
}
};
d.subscribe4 = function(topic,callback) {
if (!cache[topic]) {
cache[topic] = [];
}
cache[topic].push(callback);
return [topic, callback];
};
d.unsubscribe4 = function(handle) {
var topic = handle[0];
if (cache[topic]) {
var currentCache = cache[topic];
for (var i = 0, j = currentCache.length; i < j; i++) {
if (currentCache[i] === handle[1]) {
currentCache.splice(i, 1);
}
}
}
};
})(jQuery);
/*
using jquery 1.7 $.Callback
*/
(function(jQuery) {
var topics = {};
jQuery.Topic = function( id ) {
var callbacks,
method,
topic = id && topics[ id ];
if ( !topic ) {
callbacks = jQuery.Callbacks();
topic = {
publish: callbacks.fire,
subscribe: callbacks.add,
unsubscribe: callbacks.remove
};
if ( id ) {
topics[ id ] = topic;
}
}
return topic;
};
})(jQuery);
var PubSub = function PubSub(obj_or_alsoPassPath_or_unique, alsoPassPath_or_unique, uniqueName){
var unique = "_sub",
passPath = false,
bindTo = this;
if (typeof(uniqueName) === "string"){
unique = uniqueName;
} else if (typeof(alsoPassPath_or_unique) === "string"){
unique = alsoPassPath_or_unique;
} else if (typeof(obj_or_alsoPassPath_or_unique) === "string"){
unique = obj_or_alsoPassPath_or_unique;
}
if (typeof(alsoPassPath_or_unique) === "boolean"){
passPath = alsoPassPath_or_unique;
} else if (typeof(obj_or_alsoPassPath_or_unique) === "boolean"){
passPath = obj_or_alsoPassPath_or_unique;
}
if (typeof(obj_or_alsoPassPath_or_unique) === "object" || typeof(obj_or_alsoPassPath_or_unique) === "function"){
bindTo = obj_or_alsoPassPath_or_unique;
}
// all subscriptions, nested.
var subscriptions = {};
subscriptions[unique] = [];
// Removes all instances of handler from the passed subscription chunk.
var _unsubscribe = function(cache, handler){
for(var i = 0; i < cache[unique].length; i++){
if(handler === undefined || handler === null || cache[unique][i] === handler){
cache[unique].splice(i, 1);
i--;
}
}
};
// Recursively removes all instances of handler from the passed subscription chunk.
var _deepUnsubscribe = function(cache, handler){
for(sub in cache){
if(typeof(cache[sub]) !== "object" || sub === unique || !cache.hasOwnProperty(sub)) continue;
_deepUnsubscribe(cache[sub], handler);
}
_unsubscribe(cache, handler);
};
// Calls all handlers on the path to the passed subscription.
// ie, "a.b.c" would call "c", then "b", then "a".
// If any handler returns false, the event does not bubble up (all handlers at that level are still called)
bindTo.publish5 = function(sub, callback_args){
var args;
if (arguments.length > 2) {
// If passing args as a set of args instead of an array, grab all but the first.
args = Array.prototype.slice.apply(arguments, [1]);
} else if (callback_args) {
args = callback_args;
} else {
args = [];
}
if (args.length === undefined){
args = [args];
}
var cache = subscriptions;
var stack = [];
sub = sub || "";
var s = sub.split(".");
if (passPath) args.push(s);
stack.push(cache);
for(var i = 0; i < s.length && s[i] !== ""; i++){
if(cache[s[i]] === undefined) break;
cache = cache[s[i]];
stack.push(cache);
}
var c;
var exit = false;
while((c = stack.pop())){
for(var j = 0; j < c[unique].length; j++){
if(c[unique][j].apply(this,args) === false) exit = true;
}
if (exit) break;
}
return bindTo;
};
bindTo.subscribe5 = function(sub, handler){
var cache = subscriptions;
sub = sub || "";
var s = sub.split(".");
for(var i = 0; i < s.length && s[i] !== ""; i++){
if (!cache[s[i]]){
cache[s[i]] = {};
cache[s[i]][unique] = [];
}
cache = cache[s[i]];
}
cache[unique].push(handler);
return bindTo;
};
// Removes _all_ identical handlers from the subscription.
// If no handler is passed, all are removed.
// If deep, recursively removes handlers beyond the passed sub.
bindTo.unsubscribe5 = function(sub, handler, deep){
var cache = subscriptions;
sub = sub || "";
if (sub != ""){
var s = sub.split(".");
for(var i = 0; i < s.length && s[i] !== ""; i++){
if(cache[s[i]] === undefined) return;
cache = cache[s[i]];
}
}
if (typeof(handler) === "boolean") {
deep = handler;
handler = null;
}
if (deep){
_deepUnsubscribe(cache, handler);
} else {
_unsubscribe(cache, handler);
}
return bindTo;
};
};
PubSub(jQuery);
delete PubSub;
</script>
$.subscribe5('foo', function() {
1 + 1;
});
$.publish5('foo', ['bar']);
$.unsubscribe5('foo');
Ready to run.
Test | Ops/sec | |
---|---|---|
Object cache (Higgins) |
| ready |
jQuery events |
| ready |
higgins inspired |
| ready |
higgins again |
| ready |
jQuery $.Callbacks |
| ready |
You can edit these tests or add more tests to this page by appending /edit to the URL.