Handlebars VS TemplateEngine

JavaScript performance comparison

Revision 4 of this test case created by Jason Miller

Info

Handlebars.js (1.0.0 b6, current)

vs

TemplateEngine (whatever was current at the time)

Every 10 iterations, I have chosen to re-compile Handlebars' template, because in the real world there is more than one template in an app. Pre-compiling templates server-side is not an option for the purposes of this test (user-created templates). This means these tests assume the same template is being merged only 10 times.

Preparation code

<script src="http://cloud.github.com/downloads/wycats/handlebars.js/handlebars-1.0.0.beta.6.js?"></script>

<script src="http://html5man.com/jslibs/TemplateEngine.js?"></script>

<!-- TemplateEngine 1.2 (formerly 2) -->
<script src="http://dFL8.me/3f6e1"></script>

<!-- TemplateEngine 1.8 -->
<script src="http://dFL8.me/3f6fd"></script>

<!-- TemplateEngine 1.8.1 -->
<script src="http://pastebin.com/raw.php?i=yjVhsmqe"></script>

<!-- TemplateEngine 1.8.2 -->
<script src="http://dFL8.me/3f70e"></script>

<div id="base"></div>


<script id="template-handlebars" type="text/template"><![CDATA[
    <div class="foo1">
        <h2>{{title}}</h2>
        <h4>Iterating over an object:</h4>
        <ul>
            {{#each list}}
                <li>{{this}}</li>
            {{/each}}
        </ul>
        <h4>Iterating over an array:</h4>
        <ol>
            {{#each arr}}
                <li>{{this}}</li>
            {{/each}}
        </ol>
        <h4>Recursive nesting:</h4>
        <ul>
            {{#each nest1}}
                <li>
                    <ol>
                        {{#each this}}
                            <li>{{this}}</li>
                        {{/each}}
                    </ol>
                </li>
            {{/each}}
        </ul>
    </div>
]]></script>


<script id="template-templateengine" type="text/template"><![CDATA[
    <div class="foo1">
        <h2>{{title}}</h2>
        <h4>Iterating over an object:</h4>
        <ul>
            {{#each list}}
                <li>{{.}}</li>
            {{/each}}
        </ul>
        <h4>Iterating over an array:</h4>
        <ol>
            {{#each arr}}
                <li>{{.}}</li>
            {{/each}}
        </ol>
        <h4>Recursive nesting:</h4>
        <ul>
            {{#each nest1}}
                <li>
                    <ol>
                        {{#each .}}
                            <li>{{.}}</li>
                        {{/each}}
                    </ol>
                </li>
            {{/each}}
        </ul>
    </div>
]]></script>
<script>
Benchmark.prototype.setup = function() {
    /** NOTE: Handlebars does not support #each for Objects by default. We have to re-implement the each block helper to get that functionality back. The code below is a slightly modified version of the example from the Handlebars website. */
    Handlebars.registerHelper('each', function(context, options) {
        var ret = "";
        for(var i in context) {
            if (context.hasOwnProperty(i)) {
                ret = ret + options.fn(context[i]);
            }
        }
        return ret;
    });
   
    //----------------------------
   
    var n = document.getElementById('template-handlebars');
    var handlebarsTpl = (n.textContent || n.nodeValue || '').replace(/(^<\!\[CDATA\[|\]\]>$)/gm,'');
   
    n = document.getElementById('template-templateengine');
    var templateEngineTpl = (n.textContent || n.nodeValue || '').replace(/(^<\!\[CDATA\[|\]\]>$)/gm,'');
   
    var base = document.getElementById('base');
   
    var context = {
            title : "Template Standoff",
            list : {
                test : "test value",
                test2 : "test 2 value",
                test3 : "test 3 value",
            },
            arr : [
                "array value 1",
                "array value 2",
                "array value 3",
                "array value 4"
            ],
            nest1 : {
                foo : [
                    "nested level 2, item 1, child 1",
                    "nested level 2, item 1, child 2",
                    "nested level 2, item 1, child 3"
                ],
                foo2 : [
                    "nested level 2, item 2, child 1",
                    "nested level 2, item 2, child 2"
                ],
                foo3 : [
                    "nested level 2, item 3, child 1",
                    "nested level 2, item 3, child 2",
                    "nested level 2, item 3, child 3",
                    "nested level 2, item 3, child 4"
                    ]
            }
        };
   
    var template;
   
    var precompiled = Handlebars.compile(handlebarsTpl);
   
    var index = 0;
   
    var html;
};
</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
Handlebars
index++;
template = Handlebars.compile(handlebarsTpl);
html = template(context);
pending…
Handlebars (pre-compiled)
index++;
if (index%10===0) {
  precompiled = Handlebars.compile(handlebarsTpl);
}
html = precompiled(context);
pending…
TemplateEngine
index++;
html = engine.template(templateEngineTpl, context);
pending…
TemplateEngine 1.2
index++;
html = engine2.template(templateEngineTpl, context);
pending…
TemplateEngine 1.8
index++;
html = engine_1_8.template(templateEngineTpl, context);
pending…
TemplateEngine 1.8.1
index++;
html = engine_1_8_1.template(templateEngineTpl, context);
pending…
TemplateEngine 1.8.2
index++;
html = engine_1_8_2.template(templateEngineTpl, context);
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