browser/metro/base/tests/mochiperf/head.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* Any copyright is dedicated to the Public Domain.
     2    http://creativecommons.org/publicdomain/zero/1.0/ */
     4 "use strict";
     6 // Load common code from ../mochitest/head.js
     7 let mochitestDir = getRootDirectory(gTestPath).replace('/mochiperf', '/mochitest');
     8 Services.scriptloader.loadSubScript(mochitestDir + "head.js", this);
    10 // Misc. constants
    11 const kInfoHeader = "PERF-TEST | ";
    12 const kDeclareId = "DECLARE ";
    13 const kResultsId = "RESULTS ";
    15 // Mochitest log data format version
    16 const kDataSetVersion = "1";
    18 /*
    19  * PerfTest - helper library for simple mochitest based performance tests.
    20  */
    22 var PerfTest = {
    23   _userStartTime: 0,
    24   _userStopTime: 0,
    26   /******************************************************
    27    * Declare and results
    28    */
    30   /*
    31    * declareTest
    32    *
    33    * Declare a test which the graph server will pick up and track.
    34    * Must be called by every test on startup. Graph server will
    35    * search for result data between this declaration and the next.
    36    *
    37    * @param aUUID string for this particular test, case sensitive.
    38    * @param aName The name of the test.
    39    * @param aCategory Top level test calegory. For example 'General',
    40    * 'Graphics', 'Startup', 'Jim's Tests'.
    41    * @param aSubCategory (optional) sub category name with aCategory.
    42    * @param aDescription A detailed description (sentence or two) of
    43    * what the test does.
    44    */
    45   declareTest: function declareTest(aUUID, aName, aCategory, aSubCategory, aDescription) {
    46     this._uid = aUUID;
    47     this._print(kDeclareId, this._toJsonStr({
    48       id: aUUID,
    49       version: kDataSetVersion,
    50       name: aName,
    51       category: aCategory,
    52       subcategory: aSubCategory,
    53       description: aDescription,
    54       buildid: Services.appinfo.appBuildID,
    55     }));
    56   },
    58   /*
    59    * declareNumericalResult
    60    *
    61    * Declare a simple numerical result.
    62    *
    63    * @param aValue numerical value to record
    64    * @param aDescription string describing the value to display on the y axis.
    65    */
    66   declareNumericalResult: function declareNumericalResult(aValue, aDescription) {
    67     this._print(kResultsId, this._toJsonStr({
    68       id: this._uid,
    69       version: kDataSetVersion,
    70       results: {
    71         r0: {
    72           value: aValue,
    73           desc: aDescription
    74         }
    75       },
    76     }));
    77   },
    79   /*
    80    * declareFrameRateResult
    81    *
    82    * Declare a frame rate for a result.
    83    *
    84    * @param aFrameCount numerical frame count
    85    * @param aRunMs run time in miliseconds
    86    * @param aDescription string describing the value to display on the y axis.
    87    */
    88   declareFrameRateResult: function declareFrameRateResult(aFrameCount, aRunMs, aDescription) {
    89     this._print(kResultsId, this._toJsonStr({
    90       id: this._uid,
    91       version: kDataSetVersion,
    92       results: {
    93         r0: {
    94           value: (aFrameCount / (aRunMs / 1000.0)),
    95           desc: aDescription
    96         }
    97       },
    98     }));
    99   },
   101   /*
   102    * declareNumericalResults
   103    *
   104    * Declare a set of numerical results.
   105    *
   106    * @param aArray an array of datapoint objects of the form:
   107    *
   108    *  [ { value: (value), desc: "description/units" }, .. ]
   109    *
   110    *  optional values:
   111    *    shareAxis - the 0 based index of a previous data point this point
   112    *    should share a y axis with.
   113    */
   114   declareNumericalResults: function declareNumericalResults(aArray) {
   115     let collection = new Object();
   116     for (let idx = 0; idx < aArray.length; idx++) {
   117       collection['r' + idx] = { value: aArray[idx].value, desc: aArray[idx].desc };
   118       if (aArray[idx].shareAxis != undefined) {
   119         collection['r' + idx].shareAxis = aArray[idx].shareAxis;
   120       }
   121     }
   122     let dataset = {
   123       id: this._uid,
   124       version: kDataSetVersion,
   125       results: collection
   126     };
   127     this._print(kResultsId, this._toJsonStr(dataset));
   128   },
   130   /******************************************************
   131    * Perf tests
   132    */
   134   perfBoundsCheck: function perfBoundsCheck(aLow, aHigh, aValue, aTestMessage) {
   135     ok(aValue < aLow || aValue > aHigh, aTestMessage);
   136   },
   138   /******************************************************
   139    * Math utilities
   140    */
   142   computeMedian: function computeMedian(aArray, aOptions) {
   143     aArray.sort(function (a, b) {
   144       return a - b;
   145     });
   147     var idx = Math.floor(aArray.length / 2);
   149     if(aArray.length % 2) {
   150         return aArray[idx];
   151     } else {
   152         return (aArray[idx-1] + aArray[idx]) / 2;
   153     }
   154   },
   156   computeAverage: function computeAverage(aArray, aOptions) {
   157     let idx;
   158     let count = 0, total = 0;
   159     let highIdx = -1, lowIdx = -1;
   160     let high = 0, low = 0;
   161     if (aOptions.stripOutliers) {
   162       for (idx = 0; idx < aArray.length; idx++) {
   163         if (high < aArray[idx]) {
   164           highIdx = idx;
   165           high = aArray[idx];
   166         }
   167         if (low > aArray[idx]) {
   168           lowIdx = idx;
   169           low = aArray[idx];
   170         }
   171       }
   172     }
   173     for (idx = 0; idx < aArray.length; idx++) {
   174       if (idx != high && idx != low) {
   175         total += aArray[idx];
   176         count++;
   177       }
   178     }
   179     return total / count;
   180   },
   182   computeHighLowBands: function computeHighLow(aArray, aPercentage) {
   183     let bandCount = Math.ceil(aArray.length * aPercentage);
   184     let lowGroup = 0, highGroup = 0;
   185     let idx;
   187     function compareNumbers(a, b) {
   188       return a - b;
   189     }
   190     aArray.sort(compareNumbers);
   191     for (idx = 0; idx < bandCount; idx++) {
   192       lowGroup += aArray[idx];
   193     }
   194     let top = aArray.length - 1;
   195     for (idx = top; idx > (top - bandCount); idx--) {
   196       highGroup += aArray[idx];
   197     }
   198     return {
   199       low: lowGroup / bandCount,
   200       high: highGroup / bandCount,
   201       ave: this.computeAverage(aArray, {})
   202     };
   203   },
   205   /******************************************************
   206    * Internal
   207    */
   209   _print: function _print() {
   210     let str = kInfoHeader;
   211     for (let idx = 0; idx < arguments.length; idx++) {
   212       str += arguments[idx];
   213     }
   214     info(str);
   215   },
   217   _toJsonStr: function _toJsonStr(aTable) {
   218     return window.JSON.stringify(aTable);
   219   },
   220 };
   222 /*
   223  * StopWatch - timing helper
   224  */
   226 function StopWatch(aStart) {
   227   if (aStart) {
   228     this.start();
   229   }
   230 }
   232 StopWatch.prototype = {
   233   /*
   234    * Start timing. Resets existing clock.
   235    */
   236   start: function start() {
   237     this.reset();
   238     this._userStartTime = window.performance.now();
   239   },
   241   /*
   242    * Stop timing.
   243    */
   244   stop: function stop() {
   245     this._userStopTime = window.performance.now();
   246     return this.time();
   247   },
   249   /*
   250    * Resets both start and end time.
   251    */
   252   reset: function reset() {
   253     this._userStartTime = this._userStopTime = 0;
   254   },
   256   /*
   257    * Returns the total time ellapsed in milliseconds. Returns zero if
   258    * no time has been accumulated.
   259    */
   260   time: function time() {
   261     if (!this._userStartTime) {
   262       return 0;
   263     }
   264     if (!this._userStopTime) {
   265       return (window.performance.now() - this._userStartTime);
   266     }
   267     return this._userStopTime - this._userStartTime;
   268   },
   269 };

mercurial