Add shared code for a new a graphics benchmark
[WebKit-https.git] / PerformanceTests / Animometer / resources / sampler.js
1 var Statistics =
2 {
3     sampleMean: function(numberOfSamples, sum)
4     {
5         if (numberOfSamples < 1)
6             return 0;
7         return sum / numberOfSamples;
8     },
9
10     // With sum and sum of squares, we can compute the sample standard deviation in O(1).
11     // See https://rniwa.com/2012-11-10/sample-standard-deviation-in-terms-of-sum-and-square-sum-of-samples/
12     unbiasedSampleStandardDeviation: function(numberOfSamples, sum, squareSum)
13     {
14         if (numberOfSamples < 2)
15             return 0;
16         return Math.sqrt((squareSum - sum * sum / numberOfSamples) / (numberOfSamples - 1));
17     },
18
19     geometricMean: function(values)
20     {
21         if (!values.length)
22             return 0;
23         var roots = values.map(function(value) { return  Math.pow(value, 1 / values.length); })
24         return roots.reduce(function(a, b) { return a * b; });
25     }   
26 }
27
28 function Experiment()
29 {
30     this._init();
31     this._maxHeap = Algorithm.createMaxHeap(Experiment.defaults.CONCERN_SIZE);
32 }
33
34 Experiment.defaults =
35 {
36     CONCERN: 5,
37     CONCERN_SIZE: 100,
38 }
39
40 Experiment.prototype =
41 {
42     _init: function()
43     {
44         this._sum = 0;
45         this._squareSum = 0;
46         this._numberOfSamples = 0;
47     },
48     
49     // Called after a warm-up period
50     startSampling: function()
51     {
52         var mean = this.mean();
53         this._init();
54         this._maxHeap.init();
55         this.sample(mean);
56     },
57     
58     sample: function(value)
59     {
60         this._sum += value;
61         this._squareSum += value * value;
62         this._maxHeap.push(value);
63         ++this._numberOfSamples;
64     },
65     
66     mean: function()
67     {
68         return Statistics.sampleMean(this._numberOfSamples, this._sum);
69     },
70     
71     standardDeviation: function()
72     {
73         return Statistics.unbiasedSampleStandardDeviation(this._numberOfSamples, this._sum, this._squareSum);
74     },
75     
76     percentage: function()
77     {
78         var mean = this.mean();
79         return mean ? this.standardDeviation() * 100 / mean : 0;
80     },
81     
82     concern: function(percentage)
83     {
84         var size = Math.ceil(this._numberOfSamples * percentage / 100);
85         var values = this._maxHeap.values(size);
86         return values.length ? values.reduce(function(a, b) { return a + b; }) / values.length : 0;
87     },
88     
89     score: function(percentage)
90     {
91         return Statistics.geometricMean([this.mean(), Math.max(this.concern(percentage), 1)]);
92     }
93 }
94
95 function Sampler(count)
96 {
97     this.experiments = [];
98     while (count--)
99         this.experiments.push(new Experiment());
100     this.samples = [];
101     this.samplingTimeOffset = 0;
102 }
103
104 Sampler.prototype =
105 {
106     startSampling: function(timeOffset)
107     {
108         for (var index = 0; index < this.experiments.length; ++index)
109             this.experiments[index].startSampling();
110             
111         this.samplingTimeOffset = timeOffset / 1000;
112     },
113     
114     sample: function(timeOffset, values)
115     {
116         if (values.length < this.experiments.length)
117             throw "Not enough sample points";
118                     
119         for (var index = 0; index < this.experiments.length; ++index)
120             this.experiments[index].sample(values[index]);
121             
122         this.samples.push({ timeOffset: timeOffset / 1000, values: values });
123     }
124 }