Handlebars-vs-Mini-Handlebars

JavaScript performance comparison

Test case created by Mike Smullin

Info

benching my minimalist alternative to the official lib

Preparation code

<script src="http://cloud.github.com/downloads/wycats/handlebars.js/handlebars-1.0.rc.1.js"></script>
<script>
Benchmark.prototype.setup = function() {
    var MiniHandlebars, mini, template,
      __hasProp = {}.hasOwnProperty;
   
    MiniHandlebars = (function() {
   
      MiniHandlebars._extend = function(a, b) {
        var k, o;
        if (b == null) {
          b = {};
        }
        o = {};
        for (k in a) {
          if (!__hasProp.call(a, k)) continue;
          o[k] = a[k];
        }
        for (k in b) {
          if (!__hasProp.call(b, k)) continue;
          o[k] = b[k];
        }
        return o;
      };
   
      function MiniHandlebars(options, templates) {
        this.options = options != null ? options : {};
        this.templates = templates != null ? templates : {};
      }
   
      MiniHandlebars.prototype.render = function(t, d) {
        var k, lvl, ssplice, tok_map, toks, xshift;
        lvl = 1;
        toks = [];
        tok_map = {};
        d = MiniHandlebars._extend(this.options.locals, d);
        t.replace(/\{\{(\/\w+|\w+)( [\w, ]+)?\}\}\s*/g, function() {
          var block, close_func, level, name, tok;
          close_func = arguments[1][0] === '/';
          tok = {
            match: arguments[0],
            name: name = close_func ? arguments[1].slice(1) : arguments[1],
            block: block = typeof arguments[2] === 'string',
            args: (block && arguments[2].replace(/(^ +| +$)/, '').split(/, */)) || [],
            "var": block === close_func,
            level: level = (block === close_func && lvl) || (block && lvl++) || (close_func && --lvl),
            key: level + '.' + name,
            pos: arguments[3]
          };
          if (level !== 1) {
            return arguments[0];
          }
          if (close_func) {
            toks[tok_map[tok.key]].mate = tok;
          }
          if (tok["var"] || tok.block) {
            tok_map[tok.key] = toks.push(tok) - 1;
          }
          return arguments[0];
        });
        xshift = 0;
        for (k in toks) {
          if (!(toks[k].level === 1)) {
            continue;
          }
          ssplice = function(l, r) {
            t = t.substr(0, toks[k].pos + xshift) + r + t.substr(toks[k].pos + l + xshift);
            xshift += r.length - l;
          };
          if (toks[k]["var"]) {
            ssplice(toks[k].match.length, d[toks[k].name]);
          } else if (toks[k].block) {
            ssplice(toks[k].mate.pos + (toks[k].mate.match.length - toks[k].pos), d[toks[k].name].apply((function() {}), [t.substr(toks[k].pos + toks[k].match.length + xshift, toks[k].mate.pos - (toks[k].pos + toks[k].match.length)), d].concat(toks[k].args)));
          }
        }
        return t;
      };
   
      return MiniHandlebars;
   
    })();
   
    mini = new MiniHandlebars({
      locals: {
        each: function(template, data, enumerable, key, value) {
          var k, out, v, _data, _ref;
          out = '';
          _ref = data[enumerable];
          for (k in _ref) {
            if (!__hasProp.call(_ref, k)) continue;
            v = _ref[k];
            _data = MiniHandlebars._extend(v);
            _data['this'] = v;
            if (typeof key !== 'undefined') {
              _data[key] = k;
            }
            if (typeof value !== 'undefined') {
              _data[value] = v;
            }
            out += mini.render(template, _data);
          }
          return out;
        }
      }
    });
   
   
   
   
   
    var source   = '<ul class="people_list">\n{{#each people}}\n<li>{{this}}</li>\n{{/each}}\n</ul>';
   
    var template = '<ul class="people_list">\n{{each people}}\n<li>{{this}}</li>\n{{/each}}\n</ul>';
   
    var data = {
      people: ["Yehuda Katz", "Alan Johnson", "Charles Jolley"]
    };
};
</script>

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
Handlebars.compile(source)(data);
 
pending…
Mini-Handlebars
mini.render(template, data);
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:

1 comment

Eric Shelley commented :

Mike,

These results look great!

Eric

Add a comment