A Comparison of JS Publish/Subscribe Approaches

JavaScript performance comparison

Revision 36 of this test case created by pmelande

Info

A Comparison of JS Publish/Subscribe Approaches

In this comparison I'm trying to focus on event inheritance feature present in PubSubJS and my implementation of the JQuery PubSub extension. In most PubSub implementations Subscribers and Publishers have a one to one relationship. This gives them a huge performance benefit, but can be a drawback when building complex decoupled applications as you have to wire every single event. In this comparison I'm looking at a pretty standard GUI like the one on google.com. We have a HEADER region, a tool region to the LEFT, a CONTENT region and a FOOTER. Each one of these regions are dependent on each other using PubSub to communicate. A MANAGER in each region is responsible for Loading/Unloading modules. A typical PubSub message for this application would look something like this:

"/APP/REGION/MODULE/EVENT"

Using a PubSub implementation that allows for inheritance allow us to create a subscriber for "/APP/REGION" that would listen to ALL events that occur within this region. Using the simpler implementations we would have to publish two events, one for the module and one for the region.

In this example each PubSub implementation has 4 subscribers (multiplied by 10). One for APP, REGION, MODULE and EVENT each.

More info: publish/subscribe on Wikipedia.

Compared:

Preparation code

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" type="text/javascript">
</script>
<script src="https://raw.github.com/mroderick/PubSubJS/master/src/pubsub.js" type="text/javascript">
</script>
<script src="https://raw.github.com/lotaballs/bloody-jquery-plugins/master/pubsub.js" type="text/javascript">
</script>
<script src="https://raw.github.com/phiggins42/bloody-jquery-plugins/55e41df9bf08f42378bb08b93efcb28555b61aeb/pubsub.js" type="text/javascript">
</script>
<script src="https://raw.github.com/gist/1695338/736bcf94f9226d975fce3ad4f2bc08ccbf176bad/pubsub.js" type="text/javascript">
</script>
<script src="https://raw.github.com/appendto/amplify/master/core/amplify.core.js" type="text/javascript">
</script>
<script src="https://raw.github.com/maccman/spine/master/lib/spine.js" type="text/javascript">
</script>
<script src="https://raw.github.com/richardscarrott/ply/master/src/core.js" type="text/javascript">
</script>
<script type="text/javascript">
window.callback = function () {};
window.payload = {
  somekey: 'some value'
};

jQuery(function() {
    jQuery(window).on('/APP', callback);
    jQuery(window).on('/APP/REGION', callback);
    jQuery(window).on('/APP/REGION/MODULE', callback);
    jQuery(window).on('/APP/REGION/MODULE/EVENT', callback);

    PubSub.subscribe('APP', callback);
    PubSub.subscribe('APP.REGION', callback);
    PubSub.subscribe('APP.REGION.MODULE', callback);
    PubSub.subscribe('APP.REGION.MODULE.EVENT', callback);

    jQuery.subscribe('/APP', callback);
    jQuery.subscribe('/APP/REGION', callback);
    jQuery.subscribe('/APP/REGION/MODULE', callback);
    jQuery.subscribe('/APP/REGION/MODULE/EVENT', callback);

    Events.subscribe('/APP', callback);
    Events.subscribe('/APP/REGION', callback);
    Events.subscribe('/APP/REGION/MODULE', callback);
    Events.subscribe('/APP/REGION/MODULE/EVENT', callback);

    App.subscribe('/APP', callback);
    App.subscribe('/APP/REGION', callback);
    App.subscribe('/APP/REGION/MODULE', callback);
    App.subscribe('/APP/REGION/MODULE/EVENT', callback);

    amplify.subscribe('/APP', callback);
    amplify.subscribe('/APP/REGION', callback);
    amplify.subscribe('/APP/REGION/MODULE', callback);
    amplify.subscribe('/APP/REGION/MODULE/EVENT', callback);

    Spine.bind('/APP', callback);
    Spine.bind('/APP/REGION', callback);
    Spine.bind('/APP/REGION/MODULE', callback);
    Spine.bind('/APP/REGION/MODULE/EVENT', callback);

    Ply.core.listen('/APP', callback);
    Ply.core.listen('/APP/REGION', callback);
    Ply.core.listen('/APP/REGION/MODULE', callback);
    Ply.core.listen('/APP/REGION/MODULE/EVENT', callback);
 
});
</script>

Preparation code output

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
jQuery Events
jQuery(window).trigger('/APP', payload);
jQuery(window).trigger('/APP/REGION', payload);
jQuery(window).trigger('/APP/REGION/MODULE', payload);
jQuery(window).trigger('/APP/REGION/MODULE/EVENT', payload);
pending…
PubSubJS
PubSub.publish('APP.REGION.MODULE.EVENT', payload);
pending…
jQuery PubSub plugin
$.publish('/APP/REGION/MODULE/EVENT', [payload]);
pending…
Pure JS PubSub
Events.publish('/APP', [payload]);
Events.publish('/APP/REGION', [payload]);
Events.publish('/APP/REGION/MODULE', [payload]);
Events.publish('/APP/REGION/MODULE/EVENT', [payload]);
pending…
Darcy Clarke
App.publish('APP', [payload]);
App.publish('APP/REGION', [payload]);
App.publish('APP/REGION/MODULE', [payload]);
App.publish('APP/REGION/MODULE/EVENT', [payload]);
pending…
Amplify Pub/Sub
amplify.publish('/APP', payload);
amplify.publish('/APP/REGION', payload);
amplify.publish('/APP/REGION/MODULE', payload);
amplify.publish('/APP/REGION/MODULE/EVENT', payload);
pending…
Spine Events
Spine.trigger('/APP', payload);
Spine.trigger('/APP/REGION', payload);
Spine.trigger('/APP/REGION/MODULE', payload);
Spine.trigger('/APP/REGION/MODULE/EVENT', payload);
pending…
Ply Notify/Listen
Ply.core.notify('/APP', window, payload);
Ply.core.notify('/APP/REGION', window, payload);
Ply.core.notify('/APP/REGION/MODULE', window, payload);
Ply.core.notify('/APP/REGION/MODULE/EVENT', window, payload);
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment