// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. 'use strict'; base.require('guid'); base.require('range'); /** * @fileoverview Provides the Counter class. */ base.exportTo('tracing.model', function() { /** * Stores all the samples for a given counter. * @constructor */ function Counter(parent, id, category, name) { this.guid_ = tracing.GUID.allocate(); this.parent = parent; this.id = id; this.category = category || ''; this.name = name; this.seriesNames = []; this.seriesColors = []; this.timestamps = []; this.samples = []; this.bounds = new base.Range(); } Counter.prototype = { __proto__: Object.prototype, /* * @return {Number} A globally unique identifier for this counter. */ get guid() { return this.guid_; }, toJSON: function() { var obj = new Object(); var keys = Object.keys(this); for (var i = 0; i < keys.length; i++) { var key = keys[i]; if (typeof this[key] == 'function') continue; if (key == 'parent') { obj[key] = this[key].guid; continue; } obj[key] = this[key]; } return obj; }, get numSeries() { return this.seriesNames.length; }, get numSamples() { return this.timestamps.length; }, getSampleValue: function(index, seriesIndex) { return this.samples[index * this.numSeries + seriesIndex]; }, /** * Obtains min, max, avg, values, start, and end for different series for * a given counter * getSampleStatistics([0,1]) * The statistics objects that this returns are an array of objects, one * object for each series for the counter in the form: * {min: minVal, max: maxVal, avg: avgVal, start: startVal, end: endVal} * * @param {Array.<Number>} Indices to summarize. * @return {Object} An array of statistics. Each element in the array * has data for one of the series in the selected counter. */ getSampleStatistics: function(sampleIndices) { sampleIndices.sort(); var sampleIndex = this.sampleIndex; var numSeries = this.numSeries; var numSamples = this.numSamples; var ret = []; for (var i = 0; i < numSeries; ++i) { var sum = 0; var min = Number.MAX_VALUE; var max = -Number.MAX_VALUE; for (var j = 0; j < sampleIndices.length; j++) { var x = sampleIndices[j]; sum += this.getSampleValue(x, i); min = Math.min(this.getSampleValue(x, i), min); max = Math.max(this.getSampleValue(x, i), max); } var avg = sum / sampleIndices.length; var start = this.getSampleValue(sampleIndices[0], i); var end = this.getSampleValue( sampleIndices[sampleIndices.length - 1], i); ret.push({min: min, max: max, avg: avg, start: start, end: end}); } return ret; }, /** * Shifts all the timestamps inside this counter forward by the amount * specified. */ shiftTimestampsForward: function(amount) { for (var sI = 0; sI < this.timestamps.length; sI++) this.timestamps[sI] = (this.timestamps[sI] + amount); }, /** * Updates the bounds for this counter based on the samples it contains. */ updateBounds: function() { if (this.seriesNames.length != this.seriesColors.length) throw new Error('seriesNames.length must match seriesColors.length'); if (this.numSeries * this.numSamples != this.samples.length) throw new Error('samples.length must be a multiple of numSamples.'); this.totals = []; this.maxTotal = 0; this.bounds.reset(); if (this.samples.length == 0) return; this.bounds.addValue(this.timestamps[0]); this.bounds.addValue(this.timestamps[this.timestamps.length - 1]); var numSeries = this.numSeries; var maxTotal = -Infinity; for (var i = 0; i < this.timestamps.length; i++) { var total = 0; for (var j = 0; j < numSeries; j++) { total += this.samples[i * numSeries + j]; this.totals.push(total); } if (total > maxTotal) maxTotal = total; } this.maxTotal = maxTotal; } }; /** * Comparison between counters that orders by parent.compareTo, then name. */ Counter.compare = function(x, y) { var tmp = x.parent.compareTo(y); if (tmp != 0) return tmp; var tmp = x.name.localeCompare(y.name); if (tmp == 0) return x.tid - y.tid; return tmp; }; return { Counter: Counter }; });