Path: blob/trunk/third_party/closure/goog/testing/performancetable.js
4050 views
/**1* @license2* Copyright The Closure Library Authors.3* SPDX-License-Identifier: Apache-2.04*/56/**7* @fileoverview A table for showing the results of performance testing.8*9* {@see goog.testing.benchmark} for an easy way to use this functionality.10*/1112goog.setTestOnly('goog.testing.PerformanceTable');13goog.provide('goog.testing.PerformanceTable');1415goog.require('goog.asserts');16goog.require('goog.dom');17goog.require('goog.dom.TagName');18goog.require('goog.dom.safe');19goog.require('goog.string.Const');20goog.require('goog.testing.PerformanceTimer');21222324/**25* A UI widget that runs performance tests and displays the results.26* @param {Element} root The element where the table should be attached.27* @param {goog.testing.PerformanceTimer=} opt_timer A timer to use for28* executing functions and profiling them.29* @param {number=} opt_precision Number of digits of precision to include in30* results. Defaults to 0.31* @param {number=} opt_numSamples The number of samples to take. Defaults to 5.32* @constructor33* @final34*/35goog.testing.PerformanceTable = function(36root, opt_timer, opt_precision, opt_numSamples) {37'use strict';38/**39* Where the table should be attached.40* @private {Element}41*/42this.root_ = root;4344/**45* Number of digits of precision to include in results.46* Defaults to 0.47* @private {number}48*/49this.precision_ = opt_precision || 0;5051var timer = opt_timer;52if (!timer) {53timer = new goog.testing.PerformanceTimer();54timer.setNumSamples(opt_numSamples || 5);55timer.setDiscardOutliers(true);56}5758/**59* A timer for running the tests.60* @private {goog.testing.PerformanceTimer}61*/62this.timer_ = timer;6364this.initRoot_();65};666768/**69* @return {goog.testing.PerformanceTimer} The timer being used.70*/71goog.testing.PerformanceTable.prototype.getTimer = function() {72'use strict';73return this.timer_;74};757677/**78* Render the initial table.79* @private80*/81goog.testing.PerformanceTable.prototype.initRoot_ = function() {82'use strict';83goog.dom.safe.setInnerHtmlFromConstant(84goog.asserts.assert(this.root_),85goog.string.Const.from(86'<table class="test-results" cellspacing="1">' +87' <thead>' +88' <tr>' +89' <th rowspan="2">Test Description</th>' +90' <th rowspan="2">Runs</th>' +91' <th colspan="4">Results (ms)</th>' +92' </tr>' +93' <tr>' +94' <th>Average</th>' +95' <th>Median</th>' +96' <th>Std Dev</th>' +97' <th>Minimum</th>' +98' <th>Maximum</th>' +99' </tr>' +100' </thead>' +101' <tbody>' +102' </tbody>' +103'</table>'));104};105106107/**108* @return {!Element} The body of the table.109* @private110*/111goog.testing.PerformanceTable.prototype.getTableBody_ = function() {112'use strict';113return goog.dom.getElementsByTagName(114goog.dom.TagName.TBODY, goog.asserts.assert(this.root_))[0];115};116117118/**119* Round to the specified precision.120* @param {number} num The number to round.121* @return {string} The rounded number, as a string.122* @private123*/124goog.testing.PerformanceTable.prototype.round_ = function(num) {125'use strict';126var factor = Math.pow(10, this.precision_);127return String(Math.round(num * factor) / factor);128};129130131/**132* Run the given function with the performance timer, and show the results.133* @param {Function} fn The function to run.134* @param {string=} opt_desc A description to associate with this run.135*/136goog.testing.PerformanceTable.prototype.run = function(fn, opt_desc) {137'use strict';138this.runTask(139new goog.testing.PerformanceTimer.Task(/** @type {function()} */ (fn)),140opt_desc);141};142143144/**145* Run the given task with the performance timer, and show the results.146* @param {goog.testing.PerformanceTimer.Task} task The performance timer task147* to run.148* @param {string=} opt_desc A description to associate with this run.149*/150goog.testing.PerformanceTable.prototype.runTask = function(task, opt_desc) {151'use strict';152var results = this.timer_.runTask(task);153this.recordResults(results, opt_desc);154};155156157/**158* Record a performance timer results object to the performance table. See159* `goog.testing.PerformanceTimer` for details of the format of this160* object.161* @param {Object} results The performance timer results object.162* @param {string=} opt_desc A description to associate with these results.163*/164goog.testing.PerformanceTable.prototype.recordResults = function(165results, opt_desc) {166'use strict';167var average = results['average'];168var standardDeviation = results['standardDeviation'];169var isSuspicious = average < 0 || standardDeviation > average * .5;170var resultsRow = goog.dom.createDom(171goog.dom.TagName.TR, null,172goog.dom.createDom(173goog.dom.TagName.TD, 'test-description',174opt_desc || 'No description'),175goog.dom.createDom(176goog.dom.TagName.TD, 'test-count', String(results['count'])),177goog.dom.createDom(178goog.dom.TagName.TD, 'test-average', this.round_(average)),179goog.dom.createDom(180goog.dom.TagName.TD, 'test-median', String(results['median'])),181goog.dom.createDom(182goog.dom.TagName.TD, 'test-standard-deviation',183this.round_(standardDeviation)),184goog.dom.createDom(185goog.dom.TagName.TD, 'test-minimum', String(results['minimum'])),186goog.dom.createDom(187goog.dom.TagName.TD, 'test-maximum', String(results['maximum'])));188if (isSuspicious) {189resultsRow.className = 'test-suspicious';190}191this.getTableBody_().appendChild(resultsRow);192};193194195/**196* Report an error in the table.197* @param {*} reason The reason for the error.198*/199goog.testing.PerformanceTable.prototype.reportError = function(reason) {200'use strict';201this.getTableBody_().appendChild(goog.dom.createDom(202goog.dom.TagName.TR, null,203goog.dom.createDom(204goog.dom.TagName.TD, {'class': 'test-error', 'colSpan': 5},205String(reason))));206};207208209