| // Copyright 2009 The Closure Library Authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS-IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| /** |
| * @fileoverview A table for showing the results of performance testing. |
| * |
| * {@see goog.testing.benchmark} for an easy way to use this functionality. |
| * |
| * @author attila@google.com (Attila Bodis) |
| * @author nicksantos@google.com (Nick Santos) |
| */ |
| |
| goog.provide('goog.testing.PerformanceTable'); |
| |
| goog.require('goog.dom'); |
| goog.require('goog.dom.TagName'); |
| goog.require('goog.testing.PerformanceTimer'); |
| |
| |
| |
| /** |
| * A UI widget that runs performance tests and displays the results. |
| * @param {Element} root The element where the table should be attached. |
| * @param {goog.testing.PerformanceTimer=} opt_timer A timer to use for |
| * executing functions and profiling them. |
| * @param {number=} opt_precision Number of digits of precision to include in |
| * results. Defaults to 0. |
| * @param {number=} opt_numSamples The number of samples to take. Defaults to 5. |
| * @constructor |
| * @final |
| */ |
| goog.testing.PerformanceTable = function( |
| root, opt_timer, opt_precision, opt_numSamples) { |
| /** |
| * Where the table should be attached. |
| * @private {Element} |
| */ |
| this.root_ = root; |
| |
| /** |
| * Number of digits of precision to include in results. |
| * Defaults to 0. |
| * @private {number} |
| */ |
| this.precision_ = opt_precision || 0; |
| |
| var timer = opt_timer; |
| if (!timer) { |
| timer = new goog.testing.PerformanceTimer(); |
| timer.setNumSamples(opt_numSamples || 5); |
| timer.setDiscardOutliers(true); |
| } |
| |
| /** |
| * A timer for running the tests. |
| * @private {goog.testing.PerformanceTimer} |
| */ |
| this.timer_ = timer; |
| |
| this.initRoot_(); |
| }; |
| |
| |
| /** |
| * @return {goog.testing.PerformanceTimer} The timer being used. |
| */ |
| goog.testing.PerformanceTable.prototype.getTimer = function() { |
| return this.timer_; |
| }; |
| |
| |
| /** |
| * Render the initial table. |
| * @private |
| */ |
| goog.testing.PerformanceTable.prototype.initRoot_ = function() { |
| this.root_.innerHTML = |
| '<table class="test-results" cellspacing="1">' + |
| ' <thead>' + |
| ' <tr>' + |
| ' <th rowspan="2">Test Description</th>' + |
| ' <th rowspan="2">Runs</th>' + |
| ' <th colspan="4">Results (ms)</th>' + |
| ' </tr>' + |
| ' <tr>' + |
| ' <th>Average</th>' + |
| ' <th>Std Dev</th>' + |
| ' <th>Minimum</th>' + |
| ' <th>Maximum</th>' + |
| ' </tr>' + |
| ' </thead>' + |
| ' <tbody>' + |
| ' </tbody>' + |
| '</table>'; |
| }; |
| |
| |
| /** |
| * @return {Element} The body of the table. |
| * @private |
| */ |
| goog.testing.PerformanceTable.prototype.getTableBody_ = function() { |
| return this.root_.getElementsByTagName(goog.dom.TagName.TBODY)[0]; |
| }; |
| |
| |
| /** |
| * Round to the specified precision. |
| * @param {number} num The number to round. |
| * @return {string} The rounded number, as a string. |
| * @private |
| */ |
| goog.testing.PerformanceTable.prototype.round_ = function(num) { |
| var factor = Math.pow(10, this.precision_); |
| return String(Math.round(num * factor) / factor); |
| }; |
| |
| |
| /** |
| * Run the given function with the performance timer, and show the results. |
| * @param {Function} fn The function to run. |
| * @param {string=} opt_desc A description to associate with this run. |
| */ |
| goog.testing.PerformanceTable.prototype.run = function(fn, opt_desc) { |
| this.runTask( |
| new goog.testing.PerformanceTimer.Task(/** @type {function()} */ (fn)), |
| opt_desc); |
| }; |
| |
| |
| /** |
| * Run the given task with the performance timer, and show the results. |
| * @param {goog.testing.PerformanceTimer.Task} task The performance timer task |
| * to run. |
| * @param {string=} opt_desc A description to associate with this run. |
| */ |
| goog.testing.PerformanceTable.prototype.runTask = function(task, opt_desc) { |
| var results = this.timer_.runTask(task); |
| this.recordResults(results, opt_desc); |
| }; |
| |
| |
| /** |
| * Record a performance timer results object to the performance table. See |
| * {@code goog.testing.PerformanceTimer} for details of the format of this |
| * object. |
| * @param {Object} results The performance timer results object. |
| * @param {string=} opt_desc A description to associate with these results. |
| */ |
| goog.testing.PerformanceTable.prototype.recordResults = function( |
| results, opt_desc) { |
| var average = results['average']; |
| var standardDeviation = results['standardDeviation']; |
| var isSuspicious = average < 0 || standardDeviation > average * .5; |
| var resultsRow = goog.dom.createDom('tr', null, |
| goog.dom.createDom('td', 'test-description', |
| opt_desc || 'No description'), |
| goog.dom.createDom('td', 'test-count', String(results['count'])), |
| goog.dom.createDom('td', 'test-average', this.round_(average)), |
| goog.dom.createDom('td', 'test-standard-deviation', |
| this.round_(standardDeviation)), |
| goog.dom.createDom('td', 'test-minimum', String(results['minimum'])), |
| goog.dom.createDom('td', 'test-maximum', String(results['maximum']))); |
| if (isSuspicious) { |
| resultsRow.className = 'test-suspicious'; |
| } |
| this.getTableBody_().appendChild(resultsRow); |
| }; |
| |
| |
| /** |
| * Report an error in the table. |
| * @param {*} reason The reason for the error. |
| */ |
| goog.testing.PerformanceTable.prototype.reportError = function(reason) { |
| this.getTableBody_().appendChild( |
| goog.dom.createDom('tr', null, |
| goog.dom.createDom('td', {'class': 'test-error', 'colSpan': 5}, |
| String(reason)))); |
| }; |