測試驅動javascript開發 — 5.效能測試

來源:互聯網
上載者:User
文章目錄
  •   1.基準和相對效能
  •   2.分析和定位瓶頸

  自動化測試另外一個比較重要的內容點是效能測試,很多問題可能有不止一種解決方案,很多時候並不知道哪個是最好的解決方案。例如有很多建立javascript對象的方法,使用javascript構造器、使用函數的方法或者使用閉包。我們可能會從可測試化、靈活性和效能的角度去考慮使用哪種方式。足見效能是相當重要的一點。

  1.基準和相對效能

  當一個問題我們有兩個以上的解決方案的時候,判斷哪個解決方案更好的原則很簡單,就是哪個的效能更好。判斷的原則也很簡單:1.建立new Date()作為開始時間;2.執行要衡量的代碼;3.代碼執行完畢,建立new Date()作為結束時間,減去開始時間算出總時間長度;4.替換執行代碼,重複上述步驟;5.比較各種方案的執行時間長度。

  每個要比較的代碼我們需要執行很多次,通常會把他們放在一個迴圈中。因為windows xp和vista作業系統的瀏覽器的timer的間隔時間是15ms,讓這個問題變的更加複雜,測試會變的相當不準確,所以我們需要保證測試代碼運行時間長度在500ms以上。

  下面是我們用來做效能測試的代碼,檔案為benchmark.js:

var ol;
function runBenchmark(name, test) {  if (!ol) {    ol = document.createElement("ol");    document.body.appendChild(ol);  }  setTimeout(function () {    var start = new Date().getTime();    test();    var total = new Date().getTime() - start;    var li = document.createElement("li");    li.innerHTML = name + ": " + total + "ms";    ol.appendChild(li);  }, 15);}

  下面的代碼使用runBenchmark()用來做測試,檔案名稱為loops.js:

var loopLength = 500000;// 填充迴圈數組var array = [];for (var i = 0; i < loopLength; i++) {  array[i] = "item" + i;}function forLoop() {  for (var i = 0, item; i < array.length; i++) {    item = array[i];  }}function forLoopCachedLength() {  for (var i = 0, l = array.length, item; i < l; i++) {    item = array[i];  }}function forLoopDirectAccess() {  for (var i = 0, item; (item = array[i]); i++) {  }}function whileLoop() {  var i = 0, item;  while (i < array.length) {    item = array[i];    i++;  }}function whileLoopCachedLength() {  var i = 0, l = array.length, item;  while (i < l) {    item = array[i];    i++;  }}function reversedWhileLoop() {  var l = array.length, item;  while (l--) {    item = array[l];  }}function doubleReversedWhileLoop() {  var l = array.length, i = l, item;  while (i--) {    item = array[l - i - 1];  }}// Run testsrunBenchmark("for-loop", forLoop);runBenchmark("for-loop, cached length", forLoopCachedLength);runBenchmark("for-loop, direct array access", forLoopDirectAccess);runBenchmark("while-loop", whileLoop);runBenchmark("while-loop, cached length property", whileLoopCachedLength);runBenchmark("reversed while-loop", reversedWhileLoop);runBenchmark("double reversed while-loop", doubleReversedWhileLoop);

  使用setTimeout方法的目的是,在測試中避免瀏覽器的堵塞。因為瀏覽器只有一個單線程,他用這一個線程完成javascript的運行、事件的觸發和頁面的渲染工作。timer則為瀏覽器提供了一個任務隊列,可以用他來處理長時間啟動並執行工作,這樣就可以避免在運行測試代碼時彈出逾時警告。

  下面我們看看loops.html頁面的內容:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html>  <head>    <title>Relative performance of loops</title>    <meta http-equiv="content-type" content="text/html; charset=UTF-8">  </head><body>  <h1>Relative performance of loops</h1>  <script type="text/javascript" src="benchmark.js"></script>  <script type="text/javascript" src="loops.js"></script></body></html>

  所有的測試做的事情都差不多,遍曆數組,並訪問每個成員。通過測試,我們可以看到哪種方式效率最高。

  我們可以把runBenchmark方法做一下重構:

var benchmark = (function () {  function init(name) {    var heading = document.createElement("h2");    heading.innerHTML = name;    document.body.appendChild(heading);    var ol = document.createElement("ol");    document.body.appendChild(ol);    return ol;  }
  function runTests(tests, view, iterations) {    for (var label in tests) {      if (!tests.hasOwnProperty(label) || typeof tests[label] != "function") {        continue;      }      (function (name, test) {        setTimeout(function () {          var start = new Date().getTime();          var l = iterations;          while (l--) {            test();          }          var total = new Date().getTime() - start;          var li = document.createElement("li");          li.innerHTML = name + ": " + total + "ms (total), " + (total / iterations) + "ms (avg)";          view.appendChild(li);        }, 15);      }(label, tests[label]));    }  }
  function benchmark(name, tests, iterations) {    iterations = iterations || 1000;    var view = init(name);    runTests(tests, view, iterations);  }
  return benchmark;}());

  使用benchmark也很簡單,如下:

var loopLength = 100000;var array = [];for (var i = 0; i < loopLength; i++) {  array[i] = "item" + i;}benchmark("Loop performance", {  "for-loop": function () {    for (var i = 0, item; i < array.length; i++) {      item = array[i];    }  },  "for-loop, cached length": function () {    for (var i = 0, l = array.length, item; i < l; i++) {      item = array[i];    }  },  // ...  "double reversed while-loop": function () {    var l = array.length, i = l, item;    while (i--) {      item = array[l - i - 1];    }  }}, 1000);

  我們也可以為benchmark擴充更多的功能,例如把最快和最慢的測試用高亮的方式顯示:

// 記錄次數var times;function runTests (tests, view, iterations) {  // ...  (function (name, test) {    // ...    var total = new Date().getTime() - start;    times[name] = total;    // ...  }(label, tests[label]));  // ...}
function highlightExtremes(view) {  // The timeout is queued after all other timers, ensuring  // that all tests are finished running and the times  // object is populated  setTimeout(function () {    var min = new Date().getTime();    var max = 0;    var fastest, slowest;    for (var label in times) {      if (!times.hasOwnProperty(label)) {        continue;      }      if (times[label] < min) {        min = times[label];        fastest = label;      }      if (times[label] > max) {        max = times[label];        slowest = label;      }    }    var lis = view.getElementsByTagName("li");    var fastRegexp = new RegExp("^" + fastest + ":");    var slowRegexp = new RegExp("^" + slowest + ":");    for (var i = 0, l = lis.length; i < l; i++) {      if (slowRegexp.test(lis[i].innerHTML)) {        lis[i].style.color = "#c00";      }      if (fastRegexp.test(lis[i].innerHTML)) {        lis[i].style.color = "#0c0";      }    }  }, 15);}// Updated benchmark functionfunction benchmark (name, tests, iterations) {  iterations = iterations || 1000;  times = {};  var view = init(name);  runTests(tests, view, iterations);  highlightExtremes(view);}

 

  2.分析和定位瓶頸

  很多瀏覽器提供了調試工具,例如firefox的firebug。這些工具可以為我們提供很多資訊,協助我們跟蹤代碼,判斷代碼中的問題。例如就是使用firebug的執行個體。

 

代碼下載:

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.