Different performance metrics.
authorOleksandr Gavenko <gavenkoa@gmail.com>
Sat, 06 Sep 2014 22:59:23 +0300
changeset 8 395195ae7daf
parent 7 d8106c8c0481
child 9 961eff57a23f
Different performance metrics.
perf.html
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/perf.html	Sat Sep 06 22:59:23 2014 +0300
@@ -0,0 +1,414 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>js perf</title>
+  <meta name="viewport" content="width=device-width,initial-scale=1.0"/>
+  <meta charset="utf-8"/>
+
+  <script src="board.js"></script>
+  <script src="perf.js"></script>
+
+  <style>
+    body {
+      width: 100%;
+    }
+    h1, div.area {
+      text-align: center;
+      margin: 10px auto;
+    }
+    #board {
+      margin: 10px auto;
+    }
+    #board td {
+      width: 40px;
+      height: 40px;
+      border: 1px solid red;
+      margin: 0;
+      text-align: center;
+    }
+
+    .test {
+      border: 1px red dotted;
+    }
+    .report {
+      border: 1px green dotted;
+    }
+  </style>
+
+</head>
+<body>
+
+  <table id="board">
+    <tr>
+      <td></td>
+      <td></td>
+      <td></td>
+      <td></td>
+    </tr>
+    <tr>
+      <td></td>
+      <td></td>
+      <td></td>
+      <td></td>
+    </tr>
+    <tr>
+      <td></td>
+      <td></td>
+      <td></td>
+      <td></td>
+    </tr>
+    <tr>
+      <td></td>
+      <td></td>
+      <td></td>
+      <td></td>
+    </tr>
+  </table>
+
+  <div class="test">
+    <button>Array vs 2d Array vs Object vs this Object</button>
+    <div class="report"></div>
+  </div>
+  
+  <script>
+    var boardDom = document.getElementById("board");
+    var ui = {};
+    ui.set = function(i, j, val) {
+      boardDom.querySelectorAll("tr")[i].querySelectorAll("td")[j].innerHTML = val;
+    }
+  </script>
+
+  <script>
+    /* var N = 1; */
+    /* var N = 1000*1000; */
+    var N = 1000*1000;
+
+    function arrNew() {
+      return [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
+    }
+    function arrGet(brd, i, j) {
+      return brd[i*4+j];
+    }
+    function arrSet(brd, i, j, val) {
+      brd[i*4+j] = val;
+    }
+    function arrPrint(brd) {
+      for (var i = 0; i < 4; i++) {
+        for (var j = 0; j < 4; j++) {
+          ui.set(i, j, brd[i*4+j]);
+        }
+      }
+    }
+    function arrRotLeft(from, to) {
+      for (var i = 0; i < 4; i++) {
+        for (var j = 0; j < 3; j++) {
+          to[i*4+j+1] = from[i*4+j];
+        }
+        to[i*4] = from[i*4+3];
+      }
+    }
+    function arrRotLeft_2(from, to) {
+      to[1] = from[0]; to[2] = from[1]; to[3] = from[2]; to[0] = from[3];
+      to[4+1] = from[4+0]; to[4+2] = from[4+1]; to[4+3] = from[4+2]; to[4+0] = from[4+3];
+      to[8+1] = from[8+0]; to[8+2] = from[8+1]; to[8+3] = from[8+2]; to[8+0] = from[8+3];
+      to[12+1] = from[12+0]; to[12+2] = from[12+1]; to[12+3] = from[12+2]; to[12+0] = from[12+3];
+    }
+
+    var L = arrNew();
+    L[2*4+3] = 5;
+    for (var i = 0; i < 4; i++) {
+      arrSet(L, i, 3-i, i+1);
+    }
+    var R = arrNew();
+
+    /* Example of plain performance calculation. */
+    var tsFrom = new Date().getTime();
+    for (var i = 0; i < N; i++) {
+      arrRotLeft(L, R);
+      arrRotLeft(R, L);
+    }
+    var tsTo = new Date().getTime();
+    arrPrint(L);
+    console.log("arrRotLeft: %f ms, %d u/s", tsTo-tsFrom, 2*i/(tsTo - tsFrom)*1000);
+
+    perf("arrRotLeft", function() {
+      arrRotLeft(this.L, this.R);
+      arrRotLeft(this.R, this.L);
+    }, N, {L: L, R: R});
+    arrPrint(L);
+
+    perf("arrRotLeft_2", function() {
+      arrRotLeft_2(this.L, this.R);
+      arrRotLeft_2(this.R, this.L);
+    }, N, {L: L, R: R});
+    arrPrint(L);
+
+
+    perf("BoardArr.prototype.copy|new", function() {
+      this.brd = this.brd.copy();
+    }, N, {brd: new BoardArr()});
+    perf("BoardArr.prototype.copy|from-to", function() {
+      this.from.copy(this.to);
+    }, N, {from: new BoardArr(), to: new BoardArr()});
+
+
+    perf("BoardArr2d.prototype.copy|new", function() {
+      this.brd = this.brd.copy();
+    }, N, {brd: new BoardArr2d()});
+    perf("BoardArr2d.prototype.copy|from-to", function() {
+      this.from.copy(this.to);
+    }, N, {from: new BoardArr2d(), to: new BoardArr2d()});
+    perf("BoardArr2d.prototype.shiftLeft_unrolled", function() {
+      this.from.shiftLeft_unrolled(this.to);
+      var swap = this.from; this.from = this.to, this.to = swap;
+    }, N, {from: new BoardArr2d(), to: new BoardArr2d()});
+    perf("BoardArr2d.prototype.shiftLeft_mostly_unrolled", function() {
+      this.from.shiftLeft_mostly_unrolled(this.to);
+      var swap = this.from; this.from = this.to, this.to = swap;
+    }, N, {from: new BoardArr2d(), to: new BoardArr2d()});
+
+    function arr2New() {
+      return [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]];
+    }
+    function arr2Get(brd, i, j) {
+      return brd[i][j];
+    }
+    function arr2Set(brd, i, j, val) {
+      brd[i][j] = val;
+    }
+    function arr2Print(brd) {
+      for (var i = 0; i < 4; i++) {
+        for (var j = 0; j < 4; j++) {
+          ui.set(i, j, brd[i][j]);
+        }
+      }
+    }
+    function arr2RotLeft(from, to) {
+      for (var i = 0; i < 4; i++) {
+        for (var j = 0; j < 3; j++) {
+          to[i][j+1] = from[i][j];
+        }
+        to[i][0] = from[i][3];
+      }
+    }
+    function arr2RotLeft_2(from, to) {
+      to[0][1] = from[0][0]; to[0][2] = from[0][1]; to[0][3] = from[0][2]; to[0][0] = from[0][3];
+      to[1][1] = from[1][0]; to[1][2] = from[1][1]; to[1][3] = from[1][2]; to[1][0] = from[1][3];
+      to[2][1] = from[2][0]; to[2][2] = from[2][1]; to[2][3] = from[2][2]; to[2][0] = from[2][3];
+      to[3][1] = from[3][0]; to[3][2] = from[3][1]; to[3][3] = from[3][2]; to[3][0] = from[3][3];
+    }
+    function arr2ShiftRight(from, to) {
+      for (var i = 0; i < 4; i++) {
+        if (from[i][2] == from[i][3]) {
+          to[i][3] = from[i][3] + 1;
+          if (from[i][0] == from[i][1]) {
+            to[i][2] = from[i][1] + 1;
+            to[i][1] = 0;
+          } else {
+            to[i][2] = from[i][1];
+            to[i][1] = from[i][0];
+          }
+          to[i][0] = 0;
+        } else {
+          to[i][3] = from[i][3];
+          if (from[i][1] == from[i][2]) {
+            to[i][2] = from[i][2] + 1;
+            to[i][1] = from[i][0];
+            to[i][0] = 0;
+          } else {
+            to[i][2] = from[i][2];
+            if (from[i][0] == from[i][1]) {
+              to[i][1] = from[i][1] + 1;
+              to[i][0] = 0;
+            } else {
+              to[i][1] = from[i][1];
+              to[i][0] = from[i][0];
+            }
+          }
+        }
+      }
+    }
+    function arr2ShiftLeft(from, to) {
+      for (var i = 3; i >= 0; i--) {
+        if (from[i][0] == from[i][1]) {
+          to[i][0] = from[i][0] + 1;
+          if (from[i][2] == from[i][3]) {
+            to[i][1] = from[i][2] + 1;
+            to[i][2] = 0;
+          } else {
+            to[i][1] = from[i][2];
+            to[i][2] = from[i][3];
+          }
+          to[i][3] = 0;
+        } else {
+          to[i][0] = from[i][0];
+          if (from[i][1] == from[i][2]) {
+            to[i][1] = from[i][1] + 1;
+            to[i][2] = from[i][3];
+            to[i][3] = 0;
+          } else {
+            to[i][1] = from[i][1];
+            if (from[i][2] == from[i][3]) {
+              to[i][2] = from[i][2] + 1;
+              to[i][3] = 0;
+            } else {
+              to[i][2] = from[i][2];
+              to[i][3] = from[i][3];
+            }
+          }
+        }
+      }
+    }
+    function arr2ShiftUp(from, to) {
+      for (var j = 3; j >= 0; j--) {
+        if (from[0][j] == from[1][j]) {
+          to[0][j] = from[0][j] + 1;
+          if (from[2][j] == from[3][j]) {
+            to[1][j] = from[2][j] + 1;
+            to[2][j] = 0;
+          } else {
+            to[1][j] = from[2][j];
+            to[2][j] = from[3][j];
+          }
+          to[3][j] = 0;
+        } else {
+          to[0][j] = from[0][j];
+          if (from[1][j] == from[2][j]) {
+            to[1][j] = from[1][j] + 1;
+            to[2][j] = from[3][j];
+            to[3][j] = 0;
+          } else {
+            to[1][j] = from[1][j];
+            if (from[2][j] == from[3][j]) {
+              to[2][j] = from[2][j] + 1;
+              to[3][j] = 0;
+            } else {
+              to[2][j] = from[2][j];
+              to[3][j] = from[3][j];
+            }
+          }
+        }
+      }
+    }
+    function arr2ShiftDown(from, to) {
+      for (var j = 0; j < 4; j++) {
+        if (from[2][j] == from[3][j]) {
+          to[3][j] = from[3][j] + 1;
+          if (from[0][j] == from[1][j]) {
+            to[2][j] = from[1][j] + 1;
+            to[1][j] = 0;
+          } else {
+            to[2][j] = from[1][j];
+            to[1][j] = from[0][j];
+          }
+          to[0][j] = 0;
+        } else {
+          to[3][j] = from[3][j];
+          if (from[1][j] == from[2][j]) {
+            to[2][j] = from[2][j] + 1;
+            to[1][j] = from[0][j];
+            to[0][j] = 0;
+          } else {
+            to[2][j] = from[2][j];
+            if (from[0][j] == from[1][j]) {
+              to[1][j] = from[1][j] + 1;
+              to[0][j] = 0;
+            } else {
+              to[1][j] = from[1][j];
+              to[0][j] = from[0][j];
+            }
+          }
+        }
+      }
+    }
+    var L = arr2New();
+    L[2][3] = 5;
+    for (var i = 0; i < 4; i++) {
+      arr2Set(L, i, 3-i, i+1);
+    }
+
+    var R = arr2New();
+    var tsFrom = new Date().getTime();
+    for (var i = 0; i < N; i++) {
+      arr2RotLeft(L, R);
+      arr2RotLeft(R, L);
+    }
+    var tsTo = new Date().getTime();
+    /* arr2Print(L); */
+    console.log("arr2RotLeft: %f ms, %d u/s", tsTo-tsFrom, 2*i/(tsTo - tsFrom)*1000);
+
+    var tsFrom = new Date().getTime();
+    for (var i = 0; i < N; i++) {
+      arr2RotLeft_2(L, R);
+      arr2RotLeft_2(R, L);
+    }
+    var tsTo = new Date().getTime();
+    /* arr2Print(L); */
+    console.log("arr2RotLeft_2: %f ms, %d u/s", tsTo-tsFrom, 2*i/(tsTo - tsFrom)*1000);
+
+
+    var objMap = [["aa", "ab", "ac", "ad"], ["ba", "bb", "bc", "bd"], ["ca", "cb", "cc", "cd"], ["da", "db", "dc", "dd"]];
+    function objNew() {
+      return { aa: 0, ab: 0, ac: 0, ad: 0,
+               ba: 0, bb: 0, bc: 0, bd: 0,
+               ca: 0, cb: 0, cc: 0, cd: 0,
+               da: 0, db: 0, dc: 0, dd: 0 };
+    }
+    function objGet(brd, i, j) {
+      return brd[objMap[i][j]];
+    }
+    function objSet(brd, i, j, val) {
+      brd[objMap[i][j]] = val;
+    }
+    function objPrint(brd) {
+      ui.set(0, 0, brd.aa); ui.set(0, 1, brd.ab); ui.set(0, 2, brd.ac); ui.set(0, 3, brd.ad);
+      ui.set(1, 0, brd.ba); ui.set(1, 1, brd.bb); ui.set(1, 2, brd.bc); ui.set(1, 3, brd.bd);
+      ui.set(2, 0, brd.ca); ui.set(2, 1, brd.cb); ui.set(2, 2, brd.cc); ui.set(2, 3, brd.cd);
+      ui.set(3, 0, brd.da); ui.set(3, 1, brd.db); ui.set(3, 2, brd.dc); ui.set(3, 3, brd.dd);
+    }
+    function objRotLeft(from, to) {
+      to.ab = from.aa; to.ac = from.ab; to.ad = from.ac; to.aa = from.ad;
+      to.bb = from.ba; to.bc = from.bb; to.bd = from.bc; to.ba = from.bd;
+      to.cb = from.ca; to.cc = from.cb; to.cd = from.cc; to.ca = from.cd;
+      to.db = from.da; to.dc = from.db; to.dd = from.dc; to.da = from.dd;
+    }
+    function objRotLeft_2(from, to) {
+      to["ab"] = from["aa"]; to["ac"] = from["ab"]; to["ad"] = from["ac"]; to["aa"] = from["ad"];
+      to["bb"] = from["ba"]; to["bc"] = from["bb"]; to["bd"] = from["bc"]; to["ba"] = from["bd"];
+      to["cb"] = from["ca"]; to["cc"] = from["cb"]; to["cd"] = from["cc"]; to["ca"] = from["cd"];
+      to["db"] = from["da"]; to["dc"] = from["db"]; to["dd"] = from["dc"]; to["da"] = from["dd"];
+    }
+    var L = objNew();
+    L.cd = 5;
+    for (var i = 0; i < 4; i++) {
+      objSet(L, i, 3-i, i+1);
+    }
+
+    var R = objNew();
+    var tsFrom = new Date().getTime();
+    for (var i = 0; i < N; i++) {
+      objRotLeft(L, R);
+      objRotLeft(R, L);
+    }
+    var tsTo = new Date().getTime();
+    objPrint(L);
+    console.log("objRotLeft: %f ms, %d u/s", tsTo-tsFrom, 2*i/(tsTo - tsFrom)*1000);
+
+    var tsFrom = new Date().getTime();
+    for (var i = 0; i < N; i++) {
+      objRotLeft_2(L, R);
+      objRotLeft_2(R, L);
+    }
+    var tsTo = new Date().getTime();
+    objPrint(L);
+    console.log("objRotLeft_2: %f ms, %d u/s", tsTo-tsFrom, 2*i/(tsTo - tsFrom)*1000);
+  </script>
+
+  <script>
+    /* console.log(Array.prototype.map.call(document.querySelectorAll("button"), function(x){return x;})); */
+    Array.prototype.forEach.call(document.querySelectorAll("button"), function(btn) {
+      console.log(btn)
+    });
+  </script>
+</body>
+</html>