Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / remoting / webapp / base / js / stats_accumulator.js
blobe0edd49653807203dd25b333d7c5f2af697fc45f
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 /**
6  * @fileoverview
7  * The webapp reads the plugin's connection statistics frequently (once per
8  * second). It logs statistics to the server less frequently, to keep
9  * bandwidth and storage costs down. This class bridges that gap, by
10  * accumulating high-frequency numeric data, and providing statistics
11  * summarising that data.
12  */
14 'use strict';
16 /** @suppress {duplicate} */
17 var remoting = remoting || {};
19 /**
20  * @constructor
21  */
22 remoting.StatsAccumulator = function() {
23   /**
24    * A map from names to lists of values.
25    * @private {Object<Array<number>>}
26    */
27   this.valueLists_ = {};
29   /**
30    * The first time, after this object was most recently initialized or emptied,
31    * at which a value was added to this object.
32    * @private {?number}
33    */
34   this.timeOfFirstValue_ = null;
37 /**
38  * Adds values to this object.
39  *
40  * @param {Object<number>} newValues
41  */
42 remoting.StatsAccumulator.prototype.add = function(newValues) {
43   for (var key in newValues) {
44     this.getValueList(key).push(newValues[key]);
45   }
46   if (this.timeOfFirstValue_ === null) {
47     this.timeOfFirstValue_ = new Date().getTime();
48   }
51 /**
52  * Empties this object.
53  */
54 remoting.StatsAccumulator.prototype.empty = function() {
55   this.valueLists_ = {};
56   this.timeOfFirstValue_ = null;
59 /**
60  * Gets the number of milliseconds since the first value was added to this
61  * object, after this object was most recently initialized or emptied.
62  *
63  * @return {number} milliseconds since the first value
64  */
65 remoting.StatsAccumulator.prototype.getTimeSinceFirstValue = function() {
66   if (this.timeOfFirstValue_ === null) {
67     return 0;
68   }
69   return new Date().getTime() - this.timeOfFirstValue_;
72 /**
73  * Calculates the mean of the values for a given key.
74  *
75  * @param {string} key
76  * @return {number} the mean of the values for that key
77  */
78 remoting.StatsAccumulator.prototype.calcMean = function(key) {
79   /**
80    * @param {Array<number>} values
81    * @return {number}
82    */
83   var calcMean = function(values) {
84     if (values.length == 0) {
85       return 0.0;
86     }
87     var sum = 0;
88     for (var i = 0; i < values.length; i++) {
89       sum += values[i];
90     }
91     return sum / values.length;
92   };
93   return this.map(key, calcMean);
96 /**
97  * Applies a given map to the list of values for a given key.
98  *
99  * @param {string} key
100  * @param {function(Array<number>): number} map
101  * @return {number} the result of applying that map to the list of values for
102  *     that key
103  */
104 remoting.StatsAccumulator.prototype.map = function(key, map) {
105   return map(this.getValueList(key));
109  * Gets the list of values for a given key.
110  * If this object contains no values for that key, then this routine creates
111  * an empty list, stores it in this object, and returns it.
113  * @private
114  * @param {string} key
115  * @return {Array<number>} the list of values for that key
116  */
117 remoting.StatsAccumulator.prototype.getValueList = function(key) {
118   var valueList = this.valueLists_[key];
119   if (!valueList) {
120     valueList = [];
121     this.valueLists_[key] = valueList;
122   }
123   return valueList;
127  * @return {?remoting.ClientSession.PerfStats} returns null if all fields are
128  *     zero.
129  */
130 remoting.StatsAccumulator.prototype.getPerfStats = function() {
131   var stats = new remoting.ClientSession.PerfStats();
132   stats.videoBandwidth = this.calcMean('videoBandwidth');
133   stats.captureLatency = this.calcMean('captureLatency');
134   stats.encodeLatency = this.calcMean('encodeLatency');
135   stats.decodeLatency = this.calcMean('decodeLatency');
136   stats.renderLatency = this.calcMean('renderLatency');
137   stats.roundtripLatency = this.calcMean('roundtripLatency');
139   for (var key in stats) {
140     if (stats[key] !== 0) {
141       return stats;
142     }
143   }
144   return null;