Javascript  |  185行  |  4.48 KB

// 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('base.guid');
base.require('base.range');
base.require('tracing.trace_model.counter_series');

/**
 * @fileoverview Provides the Counter class.
 */
base.exportTo('tracing.trace_model', function() {

  /**
   * Stores all the samples for a given counter.
   * @constructor
   */
  function Counter(parent, id, category, name) {
    this.guid_ = base.GUID.allocate();

    this.parent = parent;
    this.id = id;
    this.category = category || '';
    this.name = name;

    this.series_ = [];
    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;
    },

    set timestamps(arg) {
      throw new Error('Bad counter API. No cookie.');
    },

    set seriesNames(arg) {
      throw new Error('Bad counter API. No cookie.');
    },

    set seriesColors(arg) {
      throw new Error('Bad counter API. No cookie.');
    },

    set samples(arg) {
      throw new Error('Bad counter API. No cookie.');
    },

    addSeries: function(series) {
      this.series_.push(series);
    },

    getSeries: function(idx) {
      return this.series_[idx];
    },

    get series() {
      return this.series_;
    },

    get numSeries() {
      return this.series_.length;
    },

    get numSamples() {
      if (this.series_.length === 0)
        return 0;
      return this.series_[0].length;
    },

    get timestamps() {
      if (this.series_.length === 0)
        return [];
      return this.series_[0].timestamps;
    },

    /**
     * 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 ret = [];
      this.series_.forEach(function(series) {
        ret.push(series.getStatistics(sampleIndices));
      });
      return ret;
    },

    /**
     * Shifts all the timestamps inside this counter forward by the amount
     * specified.
     */
    shiftTimestampsForward: function(amount) {
      for (var i = 0; i < this.series_.length; ++i)
        this.series_[i].shiftTimestampsForward(amount);
    },

    /**
     * Updates the bounds for this counter based on the samples it contains.
     */
    updateBounds: function() {
      this.totals = [];
      this.maxTotal = 0;
      this.bounds.reset();

      if (this.series_.length === 0)
        return;

      var firstSeries = this.series_[0];
      var lastSeries = this.series_[this.series_.length - 1];

      this.bounds.addValue(firstSeries.getTimestamp(0));
      this.bounds.addValue(lastSeries.getTimestamp(lastSeries.length - 1));

      var numSeries = this.numSeries;
      this.maxTotal = -Infinity;

      // Sum the samples at each timestamp.
      // Note, this assumes that all series have all timestamps.
      for (var i = 0; i < firstSeries.length; ++i) {
        var total = 0;
        this.series_.forEach(function(series) {
          total += series.getSample(i).value;
          this.totals.push(total);
        }.bind(this));

        this.maxTotal = Math.max(total, this.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
  };
});