2 * Copyright (C) 2016 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 constructor(benchmark)
30 this._benchmark = benchmark;
31 for (let subResult of Results.subResults)
32 this[subResult] = new Stats(benchmark.cells[subResult], subResult);
35 get benchmark() { return this._benchmark; }
39 for (let subResult of Results.subResults)
40 this[subResult].reset();
46 this._benchmark.cells.message.classList.add('running');
52 this._benchmark.cells.message.classList.remove('running');
57 function averageAbovePercentile(numbers, percentile) {
58 // Don't change the original array.
59 numbers = numbers.slice();
61 // Sort in ascending order.
62 numbers.sort(function(a, b) { return a - b; });
64 // Now the elements we want are at the end. Keep removing them until the array size shrinks too much.
65 // Examples assuming percentile = 99:
67 // - numbers.length starts at 100: we will remove just the worst entry and then not remove anymore,
68 // since then numbers.length / originalLength = 0.99.
70 // - numbers.length starts at 1000: we will remove the ten worst.
72 // - numbers.length starts at 10: we will remove just the worst.
73 var numbersWeWant = [];
74 var originalLength = numbers.length;
75 while (numbers.length / originalLength > percentile / 100)
76 numbersWeWant.push(numbers.pop());
79 for (var i = 0; i < numbersWeWant.length; ++i)
80 sum += numbersWeWant[i];
82 var result = sum / numbersWeWant.length;
85 if (numbers.length && result < numbers[numbers.length - 1]) {
86 throw "Sanity check fail: the worst case result is " + result +
87 " but we didn't take into account " + numbers;
93 this.firstIteration.add(times[0]);
94 let steadyTimes = times.slice(1);
95 this.averageWorstCase.add(averageAbovePercentile(steadyTimes, 98));
96 this.steadyState.add(steadyTimes.reduce((previous, current) => previous + current) / steadyTimes.length);
100 reportError(message, url, lineNumber)
102 for (let subResult of Results.subResults)
103 this[subResult].reportResult(Stats.error);
105 this._benchmark.cells.message.innerHTML = url + ":" + lineNumber + ": " + message;
109 Results.subResults = ["firstIteration", "averageWorstCase", "steadyState"];