performance comparison of jQuery Template vs underscore vs string append for table

JavaScript performance comparison

Revision 33 of this test case created by

Preparation code

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js">
</script>
<script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.js">
</script>
<script src="http://documentcloud.github.com/underscore/underscore-min.js">
</script>
<script src="http://github.com/janl/mustache.js/raw/master/mustache.js">
</script>
<script src="https://raw.github.com/BorisMoore/jsrender/master/jsrender.js">
</script>
<script src="https://github.com/andyet/ICanHaz.js/raw/master/ICanHaz.min.js">
</script>
<script src="https://github.com/downloads/wycats/handlebars.js/handlebars.runtime-1.0.0.beta.6" type="text/javascript"></script>
<script>
  $(function() {
    $('body').delegate('#table .edit a, #table .select a', 'click', function() {
      var $td = $(this).closest('td');
      $td.find('input, select').show();
      $td.find('a').hide();
    });

    $('body').delegate('#table .edit .cancel, $table .select .cancel', 'click', function() {
      var $td = $(this).closest('td');
      $td.find('input, select').hide();
      $td.find('a').show();
    });
  });
</script>
<script type="text/x-jquery-tmpl" id="tmplRow">
  < tr > < td > < input type = "checkbox"
  value = "${id}" / > < /td>
  <td>${firstName} ${lastName}</td > < td class = "edit" > < a > Edit < /a>
    <input style="display:none;" type="hidden" value="Blah" / > < input class = "cancel"
  type = "button"
  value = "cancel" / > < /td>
  <td class="select">
      <a>Select</a > < select style = "display:none;" > < option > 0 < /option>
        <option>1</option > < option > 2 < /option>
        <option>3</option > < option > 4 < /option>
        <option>5</option > < option > 6 < /option>
        <option>7</option > < option > 8 < /option>
        <option>9</option > < option > 10 < /option>
       </select > < input class = "cancel"
  type = "button"
  value = "cancel" / > < /td>
   <td>More string</td > < td > More string < /td>
   <td>More string</td > < td > More string < /td>
   <td>More string</td > < td > More string < /td>
</tr >
</script>
<script>
  var data = [];

  for (var i = 0; i < 100; i++) {
    var row = {
      id: i,
      firstName: 'john',
      lastName: 'doe'
    };

    data.push(row);
  }

  $.template("savedTmpl", document.getElementById("tmplRow").innerHTML);

  var underscoreTmpl = "\
    <%for(var i=0;i<rows.length;i++){%>\
    <%var row=rows[i];%> \
    <tr> \
      <td> <input type = 'checkbox' value = '<%= row.id%>' /> </td>\
      <td><%= row.firstname%> <%= row.lastname%></td> \
      <td class = 'edit'> \
        <a> Edit </a>\
        <input style='display:none;' type='hidden' value='Blah' /> \
        <input class = 'cancel' type = 'button' value = 'cancel' /> \
      </td>\
      <td class='select'>\
          <a>Select</a> \
          <select style = 'display:none;'> \
            <option>0</option>\
            <option>1</option> \
            <option>2</option>\
            <option>3</option> \
            <option>4</option>\
            <option>5</option> \
            <option>6</option>\
            <option>7</option> \
            <option>8</option>\
            <option>9</option> \
            <option>10</option>\
           </select> \
            <input class = 'cancel' type = 'button' value = 'cancel' /> \
       </td>\
       <td>More string</td> \
       <td>More string</td>\
       <td>More string</td> \
       <td>More string</td>\
       <td>More string</td> \
       <td>More string</td>\
    </tr ><%}%>";

  var mustacheTmpl = "\
    {{#rows}}\
    <tr> \
      <td> <input type = 'checkbox' value = '{{id}}' /> </td>\
      <td>{{firstname}} {{lastname}}</td> \
      <td class = 'edit'> \
        <a> Edit </a>\
        <input style='display:none;' type='hidden' value='Blah' /> \
        <input class = 'cancel' type = 'button' value = 'cancel' /> \
      </td>\
      <td class='select'>\
          <a>Select</a> \
          <select style = 'display:none;'> \
            <option>0</option>\
            <option>1</option> \
            <option>2</option>\
            <option>3</option> \
            <option>4</option>\
            <option>5</option> \
            <option>6</option>\
            <option>7</option> \
            <option>8</option>\
            <option>9</option> \
            <option>10</option>\
           </select> \
            <input class = 'cancel' type = 'button' value = 'cancel' /> \
       </td>\
       <td>More string</td> \
       <td>More string</td>\
       <td>More string</td> \
       <td>More string</td>\
       <td>More string</td> \
       <td>More string</td>\
    </tr >{{/rows}}"

  var jsRenderTmpl = "\
    <tr> \
      <td> <input type = 'checkbox' value = '{{=id}}' /> </td>\
      <td>{{=firstname}} {{=lastname}}</td> \
      <td class = 'edit'> \
        <a> Edit </a>\
        <input style='display:none;' type='hidden' value='Blah' /> \
        <input class = 'cancel' type = 'button' value = 'cancel' /> \
      </td>\
      <td class='select'>\
          <a>Select</a> \
          <select style = 'display:none;'> \
            <option>0</option>\
            <option>1</option> \
            <option>2</option>\
            <option>3</option> \
            <option>4</option>\
            <option>5</option> \
            <option>6</option>\
            <option>7</option> \
            <option>8</option>\
            <option>9</option> \
            <option>10</option>\
           </select> \
            <input class = 'cancel' type = 'button' value = 'cancel' /> \
       </td>\
       <td>More string</td> \
       <td>More string</td>\
       <td>More string</td> \
       <td>More string</td>\
       <td>More string</td> \
       <td>More string</td>\
    </tr >";




(function() {
  var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
templates['handlebar_template'] = template(function (Handlebars,depth0,helpers,partials,data) {
  helpers = helpers || Handlebars.helpers;
  var buffer = "", stack1, tmp1, self=this, functionType="function", helperMissing=helpers.helperMissing, undef=void 0, escapeExpression=this.escapeExpression, blockHelperMissing=helpers.blockHelperMissing;

function program1(depth0,data) {
  
  var buffer = "", stack1;
  buffer += "\n<tr> \n  <td> <input type = 'checkbox' value = '";
  stack1 = helpers.id || depth0.id;
  if(typeof stack1 === functionType) { stack1 = stack1.call(depth0, { hash: {} }); }
  else if(stack1=== undef) { stack1 = helperMissing.call(depth0, "id", { hash: {} }); }
  buffer += escapeExpression(stack1) + "' /> </td>\n  <td>";
  stack1 = helpers.firstname || depth0.firstname;
  if(typeof stack1 === functionType) { stack1 = stack1.call(depth0, { hash: {} }); }
  else if(stack1=== undef) { stack1 = helperMissing.call(depth0, "firstname", { hash: {} }); }
  buffer += escapeExpression(stack1) + " ";
  stack1 = helpers.lastname || depth0.lastname;
  if(typeof stack1 === functionType) { stack1 = stack1.call(depth0, { hash: {} }); }
  else if(stack1=== undef) { stack1 = helperMissing.call(depth0, "lastname", { hash: {} }); }
  buffer += escapeExpression(stack1) + "</td> \n  <td class = 'edit'> \n    <a> Edit </a>\n    <input style='display:none;' type='hidden' value='Blah' /> \n    <input class = 'cancel' type = 'button' value = 'cancel' /> \n  </td>\n  <td class='select'>\n      <a>Select</a> \n      <select style = 'display:none;'> \n        <option>0</option>\n        <option>1</option> \n        <option>2</option>\n        <option>3</option> \n        <option>4</option>\n        <option>5</option> \n        <option>6</option>\n        <option>7</option> \n        <option>8</option>\n        <option>9</option> \n        <option>10</option>\n       </select> \n        <input class = 'cancel' type = 'button' value = 'cancel' /> \n   </td>\n   <td>More string</td> \n   <td>More string</td>\n   <td>More string</td> \n   <td>More string</td>\n   <td>More string</td> \n   <td>More string</td>\n</tr >";
  return buffer;}

  stack1 = helpers.rows || depth0.rows;
  tmp1 = self.program(1, program1, data);
  tmp1.hash = {};
  tmp1.fn = tmp1;
  tmp1.inverse = self.noop;
  if(typeof stack1 === functionType) { stack1 = stack1.call(depth0, tmp1); }
  else { stack1 = blockHelperMissing.call(depth0, stack1, tmp1); }
  if(stack1 || stack1 === 0) { buffer += stack1; }
  buffer += "\"\n";
  return buffer;});
})()


</script>
<script type="text/html" id="icanhazTmpl">
{{#rows}}
< tr > < td > < input type = "checkbox"
  value = "{{id}}" / > < /td>
  <td>{{firstName}} {{lastName}}</td > < td class = "edit" > < a > Edit < /a>
    <input style="display:none;" type="hidden" value="Blah" / > < input class = "cancel"
  type = "button"
  value = "cancel" / > < /td>
  <td class="select">
      <a>Select</a > < select style = "display:none;" > < option > 0 < /option>
        <option>1</option > < option > 2 < /option>
        <option>3</option > < option > 4 < /option>
        <option>5</option > < option > 6 < /option>
        <option>7</option > < option > 8 < /option>
        <option>9</option > < option > 10 < /option>
       </select > < input class = "cancel"
  type = "button"
  value = "cancel" / > < /td>
   <td>More string</td > < td > More string < /td>
   <td>More string</td > < td > More string < /td>
   <td>More string</td > < td > More string < /td>
</tr >
{{/rows}}
</script>
    

Preparation code output

<script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.js"> </script> <script src="http://documentcloud.github.com/underscore/underscore-min.js"> </script> <script src="http://github.com/janl/mustache.js/raw/master/mustache.js"> </script> <script src="https://raw.github.com/BorisMoore/jsrender/master/jsrender.js"> </script> <script src="https://github.com/andyet/ICanHaz.js/raw/master/ICanHaz.min.js"> </script> <script src="https://github.com/downloads/wycats/handlebars.js/handlebars.runtime-1.0.0.beta.6" type="text/javascript"></script> <script> $(function() { $('body').delegate('#table .edit a, #table .select a', 'click', function() { var $td = $(this).closest('td'); $td.find('input, select').show(); $td.find('a').hide(); }); $('body').delegate('#table .edit .cancel, $table .select .cancel', 'click', function() { var $td = $(this).closest('td'); $td.find('input, select').hide(); $td.find('a').show(); }); }); </script> <script type="text/x-jquery-tmpl" id="tmplRow"> < tr > < td > < input type = "checkbox" value = "${id}" / > < /td> <td>${firstName} ${lastName}</td > < td class = "edit" > < a > Edit < /a> <input style="display:none;" type="hidden" value="Blah" / > < input class = "cancel" type = "button" value = "cancel" / > < /td> <td class="select"> <a>Select</a > < select style = "display:none;" > < option > 0 < /option> <option>1</option > < option > 2 < /option> <option>3</option > < option > 4 < /option> <option>5</option > < option > 6 < /option> <option>7</option > < option > 8 < /option> <option>9</option > < option > 10 < /option> </select > < input class = "cancel" type = "button" value = "cancel" / > < /td> <td>More string</td > < td > More string < /td> <td>More string</td > < td > More string < /td> <td>More string</td > < td > More string < /td> </tr > </script> <script> var data = []; for (var i = 0; i < 100; i++) { var row = { id: i, firstName: 'john', lastName: 'doe' }; data.push(row); } $.template("savedTmpl", document.getElementById("tmplRow").innerHTML); var underscoreTmpl = "\ <%for(var i=0;i<rows.length;i++){%>\ <%var row=rows[i];%> \ <tr> \ <td> <input type = 'checkbox' value = '<%= row.id%>' /> </td>\ <td><%= row.firstname%> <%= row.lastname%></td> \ <td class = 'edit'> \ <a> Edit </a>\ <input style='display:none;' type='hidden' value='Blah' /> \ <input class = 'cancel' type = 'button' value = 'cancel' /> \ </td>\ <td class='select'>\ <a>Select</a> \ <select style = 'display:none;'> \ <option>0</option>\ <option>1</option> \ <option>2</option>\ <option>3</option> \ <option>4</option>\ <option>5</option> \ <option>6</option>\ <option>7</option> \ <option>8</option>\ <option>9</option> \ <option>10</option>\ </select> \ <input class = 'cancel' type = 'button' value = 'cancel' /> \ </td>\ <td>More string</td> \ <td>More string</td>\ <td>More string</td> \ <td>More string</td>\ <td>More string</td> \ <td>More string</td>\ </tr ><%}%>"; var mustacheTmpl = "\ {{#rows}}\ <tr> \ <td> <input type = 'checkbox' value = '{{id}}' /> </td>\ <td>{{firstname}} {{lastname}}</td> \ <td class = 'edit'> \ <a> Edit </a>\ <input style='display:none;' type='hidden' value='Blah' /> \ <input class = 'cancel' type = 'button' value = 'cancel' /> \ </td>\ <td class='select'>\ <a>Select</a> \ <select style = 'display:none;'> \ <option>0</option>\ <option>1</option> \ <option>2</option>\ <option>3</option> \ <option>4</option>\ <option>5</option> \ <option>6</option>\ <option>7</option> \ <option>8</option>\ <option>9</option> \ <option>10</option>\ </select> \ <input class = 'cancel' type = 'button' value = 'cancel' /> \ </td>\ <td>More string</td> \ <td>More string</td>\ <td>More string</td> \ <td>More string</td>\ <td>More string</td> \ <td>More string</td>\ </tr >{{/rows}}" var jsRenderTmpl = "\ <tr> \ <td> <input type = 'checkbox' value = '{{=id}}' /> </td>\ <td>{{=firstname}} {{=lastname}}</td> \ <td class = 'edit'> \ <a> Edit </a>\ <input style='display:none;' type='hidden' value='Blah' /> \ <input class = 'cancel' type = 'button' value = 'cancel' /> \ </td>\ <td class='select'>\ <a>Select</a> \ <select style = 'display:none;'> \ <option>0</option>\ <option>1</option> \ <option>2</option>\ <option>3</option> \ <option>4</option>\ <option>5</option> \ <option>6</option>\ <option>7</option> \ <option>8</option>\ <option>9</option> \ <option>10</option>\ </select> \ <input class = 'cancel' type = 'button' value = 'cancel' /> \ </td>\ <td>More string</td> \ <td>More string</td>\ <td>More string</td> \ <td>More string</td>\ <td>More string</td> \ <td>More string</td>\ </tr >"; (function() { var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; templates['handlebar_template'] = template(function (Handlebars,depth0,helpers,partials,data) { helpers = helpers || Handlebars.helpers; var buffer = "", stack1, tmp1, self=this, functionType="function", helperMissing=helpers.helperMissing, undef=void 0, escapeExpression=this.escapeExpression, blockHelperMissing=helpers.blockHelperMissing; function program1(depth0,data) { var buffer = "", stack1; buffer += "\n<tr> \n <td> <input type = 'checkbox' value = '"; stack1 = helpers.id || depth0.id; if(typeof stack1 === functionType) { stack1 = stack1.call(depth0, { hash: {} }); } else if(stack1=== undef) { stack1 = helperMissing.call(depth0, "id", { hash: {} }); } buffer += escapeExpression(stack1) + "' /> </td>\n <td>"; stack1 = helpers.firstname || depth0.firstname; if(typeof stack1 === functionType) { stack1 = stack1.call(depth0, { hash: {} }); } else if(stack1=== undef) { stack1 = helperMissing.call(depth0, "firstname", { hash: {} }); } buffer += escapeExpression(stack1) + " "; stack1 = helpers.lastname || depth0.lastname; if(typeof stack1 === functionType) { stack1 = stack1.call(depth0, { hash: {} }); } else if(stack1=== undef) { stack1 = helperMissing.call(depth0, "lastname", { hash: {} }); } buffer += escapeExpression(stack1) + "</td> \n <td class = 'edit'> \n <a> Edit </a>\n <input style='display:none;' type='hidden' value='Blah' /> \n <input class = 'cancel' type = 'button' value = 'cancel' /> \n </td>\n <td class='select'>\n <a>Select</a> \n <select style = 'display:none;'> \n <option>0</option>\n <option>1</option> \n <option>2</option>\n <option>3</option> \n <option>4</option>\n <option>5</option> \n <option>6</option>\n <option>7</option> \n <option>8</option>\n <option>9</option> \n <option>10</option>\n </select> \n <input class = 'cancel' type = 'button' value = 'cancel' /> \n </td>\n <td>More string</td> \n <td>More string</td>\n <td>More string</td> \n <td>More string</td>\n <td>More string</td> \n <td>More string</td>\n</tr >"; return buffer;} stack1 = helpers.rows || depth0.rows; tmp1 = self.program(1, program1, data); tmp1.hash = {}; tmp1.fn = tmp1; tmp1.inverse = self.noop; if(typeof stack1 === functionType) { stack1 = stack1.call(depth0, tmp1); } else { stack1 = blockHelperMissing.call(depth0, stack1, tmp1); } if(stack1 || stack1 === 0) { buffer += stack1; } buffer += "\"\n"; return buffer;}); })() </script> <script type="text/html" id="icanhazTmpl"> {{#rows}} < tr > < td > < input type = "checkbox" value = "{{id}}" / > < /td> <td>{{firstName}} {{lastName}}</td > < td class = "edit" > < a > Edit < /a> <input style="display:none;" type="hidden" value="Blah" / > < input class = "cancel" type = "button" value = "cancel" / > < /td> <td class="select"> <a>Select</a > < select style = "display:none;" > < option > 0 < /option> <option>1</option > < option > 2 < /option> <option>3</option > < option > 4 < /option> <option>5</option > < option > 6 < /option> <option>7</option > < option > 8 < /option> <option>9</option > < option > 10 < /option> </select > < input class = "cancel" type = "button" value = "cancel" / > < /td> <td>More string</td > < td > More string < /td> <td>More string</td > < td > More string < /td> <td>More string</td > < td > More string < /td> </tr > {{/rows}} </script>

Test runner

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

Java applet disabled.

Testing in CCBot 2.0.0 / Other 0.0.0
Test Ops/sec
jQuery templates
var html1 = $("#tmplRow").tmpl(data)
pending…
Precompiled jQuery template
var html3 = $.tmpl("savedTmpl", data);
pending…
Underscore.js
var untpl = _.template(underscoreTmpl);
var html4 = untpl({
  rows: data
});
pending…
mustache js
var html = Mustache.to_html(mustacheTmpl, {
  rows: data
});
pending…
jsrender
var html = $.render(data, jsRenderTmpl);
pending…
ICanHaz.js
var html = ich.icanhazTmpl({
  rows: data
});
pending…
Handlebars.js
var html = Handlebars.templates.handlebar_template({
  rows: 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.

0 Comments