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.
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.
16 /** @suppress {duplicate} */
17 var remoting
= remoting
|| {};
22 remoting
.StatsAccumulator = function() {
24 * A map from names to lists of values.
25 * @private {Object<Array<number>>}
27 this.valueLists_
= {};
30 * The first time, after this object was most recently initialized or emptied,
31 * at which a value was added to this object.
34 this.timeOfFirstValue_
= null;
38 * Adds values to this object.
40 * @param {Object<number>} newValues
42 remoting
.StatsAccumulator
.prototype.add = function(newValues
) {
43 for (var key
in newValues
) {
44 this.getValueList(key
).push(newValues
[key
]);
46 if (this.timeOfFirstValue_
=== null) {
47 this.timeOfFirstValue_
= new Date().getTime();
52 * Empties this object.
54 remoting
.StatsAccumulator
.prototype.empty = function() {
55 this.valueLists_
= {};
56 this.timeOfFirstValue_
= null;
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.
63 * @return {number} milliseconds since the first value
65 remoting
.StatsAccumulator
.prototype.getTimeSinceFirstValue = function() {
66 if (this.timeOfFirstValue_
=== null) {
69 return new Date().getTime() - this.timeOfFirstValue_
;
73 * Calculates the mean of the values for a given key.
76 * @return {number} the mean of the values for that key
78 remoting
.StatsAccumulator
.prototype.calcMean = function(key
) {
80 * @param {Array<number>} values
83 var calcMean = function(values
) {
84 if (values
.length
== 0) {
88 for (var i
= 0; i
< values
.length
; i
++) {
91 return sum
/ values
.length
;
93 return this.map(key
, calcMean
);
97 * Applies a given map to the list of values for a given key.
100 * @param {function(Array<number>): number} map
101 * @return {number} the result of applying that map to the list of values for
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.
114 * @param {string} key
115 * @return {Array<number>} the list of values for that key
117 remoting
.StatsAccumulator
.prototype.getValueList = function(key
) {
118 var valueList
= this.valueLists_
[key
];
121 this.valueLists_
[key
] = valueList
;
127 * @return {?remoting.ClientSession.PerfStats} returns null if all fields are
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) {