dynamic grid performance

JavaScript performance comparison

Test case created by Josh

Preparation code

<div id="testSections">
<div id="gridEmpty" style="font-size:12px;height:150px;overflow:auto;">
</div>
<div id="gridAngular" data-ng-controller="GridCtrl" style="font-size:12px;height:150px;overflow:auto;">
  <table>
    <thead>
      <tr>
        <th data-ng-repeat="header in headers">
          {{header.text}}
        </th>
      </tr>
    </thead>
    <tbody>
      <tr data-ng-repeat="row in data">
        <td data-ng-repeat="cell in row">
          {{cell}}
        </td>
      </tr>
    </tbody>
  </table>
</div>
<div id="gridKnockout" style="font-size:12px;height:150px;overflow:auto;">
  <table>
    <thead>
      <tr data-bind="foreach: headers">
        <th data-bind="text: $data.text">
        </th>
      </tr>
    </thead>
    <tbody data-bind="foreach: data">
      <tr data-bind="foreach: $data">
        <td data-bind="text: $data">
        </td>
      </tr>
    </tbody>
  </table>
</div>
</div>
<script type="text/x-handlebars-template" id="handlebarsTemplate">
  <table>
    <thead>
      <tr>
      {{#each headers}}
      <th>
      {{text}} < /th>
                                {{/each}}
      </thead>
                        <tbody>
                                {{#each data}}
                                <tr>
                                        {{#each this}}
                                        <td>{{this}}</td>
          {{/each}}
                                </tr>
        {{/each}}
                        </tbody>
   </table>
</script>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.1.min.js">
</script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.min.js">
</script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js">
</script>
<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.2.1.js">
</script>
<script>
Benchmark.prototype.setup = function() {
    var TEST_SIZE = 10;
   
    var headers = [{
      "text": "PO",
      "ordinal": 0
    }, {
      "text": "PO Date",
      "ordinal": 1
    }, {
      "text": "Due Date",
      "ordinal": 2
    }, {
      "text": "Supplier Phone",
      "ordinal": 3
    }, {
      "text": "Type",
      "ordinal": 4
    }, {
      "text": "Status",
      "ordinal": 5
    }, {
      "text": "Issued By",
      "ordinal": 6
    }, {
      "text": "Items",
      "ordinal": 7
    }, {
      "text": "Amount",
      "ordinal": 8
    }, {
      "text": "Added By",
      "ordinal": 9
    }];
   
    var data = [];
    for (var i = 0; i < TEST_SIZE; i++) {
      data.push(["1528", "4/7/12", "6/2/12", "ACME 248-555-1212", "Purchased Components", "On Order", "Brown, Charlie", "1", "$ 15,750.00", "Brown, Charlie"]);
    }
   
    //var initialState = $("#gridEmpty").html();
};

Benchmark.prototype.teardown = function() {
    //$("#testSections").html(initialState);
    $("#gridEmpty").empty();
};
</script>

Preparation code output

{{header.text}}
{{cell}}

Test runner

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

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
innerhtml
var i = 0,
    col = 0,
    ln = data.length,
    colLn = headers.length;
var html = ["<table><thead>"];

for (; col < colLn; col++) {
  html.push("<th>");
  html.push(headers[col].text);
  html.push("</th>");
}

html.push("</thead><tbody>");

for (; i < ln; i++) {
  html.push("<tr>");

  for (col = 0; col < colLn; col++) {
    html.push("<td>");
    html.push(data[i][col]);
    html.push("</td>");
  }

  html.push("</tr>");
}

html.push("</tbody></table>");
$("#gridEmpty").html(html.join(""));
pending…
doc fragment
var th, td, tr, i = 0,
    col = 0,
    ln = data.length,
    colLn = headers.length,
    doc = document.createDocumentFragment();
table = document.createElement("table"), thead = document.createElement("thead"), tbody = document.createElement("tbody");

tr = document.createElement("tr");
for (; col < colLn; col++) {
  th = document.createElement("th");
  th.textContent = headers[col].text;
  tr.appendChild(th);
}

thead.appendChild(tr);
table.appendChild(thead);

for (; i < ln; i++) {
  tr = document.createElement("tr");

  for (col = 0; col < colLn; col++) {
    td = document.createElement("td");
    td.textContent = data[i][col];
    tr.appendChild(td);
  }

  tbody.appendChild(tr);
}

table.appendChild(tbody);
doc.appendChild(table);
document.getElementById("gridEmpty").appendChild(doc);
pending…
handlebars
var template = Handlebars.compile($("#handlebarsTemplate").html());
$("#gridEmpty").html($.trim(template({
  headers: headers,
  data: data
})));
pending…
angular
// async test
console.log("angular test");

$("#gridAngular").attr("data-ng-app", "testApp");

var app = angular.module("testApp", []).run();
app.controller("GridCtrl", function($scope) {
  console.log("in controller");

  $scope.headers = headers;
  $scope.data = data;
  $scope.$digest();

  function digestCheck() {
    console.log($scope.$$phase);
    if (!$scope.$$phase) {
      deferred.resolve();
      return;
                }

                setTimeout(digestCheck, 5);
  }
 
  console.log("starting digest check");
        digestCheck();
});
pending…
knockout
ko.applyBindings({
  headers: headers,
  data: 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:

0 comments

Add a comment