Home | History | Annotate | Download | only in performance_monitor
      1 // Copyright (c) 2012 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.
      4 
      5 #include "chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_util.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/time/time.h"
     10 #include "chrome/browser/performance_monitor/metric.h"
     11 
     12 namespace performance_monitor {
     13 
     14 namespace {
     15 
     16 // Sorts the vector and returns the median. We don't need to sort it, but it is
     17 // a by-product of finding the median, and allows us to pass a pointer, rather
     18 // than construct another array.
     19 double SortAndGetMedian(std::vector<double>* values) {
     20   size_t size = values->size();
     21   if (!size)
     22     return 0.0;
     23 
     24   std::sort(values->begin(), values->end());
     25   return size % 2 == 0 ?
     26       (values->at(size / 2) + values->at((size / 2) - 1)) / 2.0 :
     27       values->at(size / 2);
     28 }
     29 
     30 }  // namespace
     31 
     32 Aggregator::Aggregator() {
     33 }
     34 
     35 Aggregator::~Aggregator() {
     36 }
     37 
     38 scoped_ptr<VectorOfMetricVectors> Aggregator::AggregateMetrics(
     39     MetricType metric_type,
     40     const Database::MetricVector* metrics,
     41     const base::Time& start,
     42     const std::vector<TimeRange>& intervals,
     43     const base::TimeDelta& resolution) {
     44   scoped_ptr<VectorOfMetricVectors> results(new VectorOfMetricVectors());
     45 
     46   Database::MetricVector::const_iterator metric = metrics->begin();
     47   while (metric != metrics->end() && metric->time < start)
     48     ++metric;
     49 
     50   // For each interval, advance the metric to the start of the interval, and
     51   // append a metric vector for the aggregated data within that interval,
     52   // according to the appropriate strategy.
     53   for (std::vector<TimeRange>::const_iterator interval = intervals.begin();
     54        interval != intervals.end(); ++interval) {
     55     while (metric != metrics->end() && metric->time < interval->start)
     56       ++metric;
     57 
     58     results->push_back(*AggregateInterval(
     59         metric_type,
     60       &metric,
     61       metrics->end(),
     62       interval == intervals.begin() ? start : interval->start,
     63       interval->end,
     64       resolution));
     65   }
     66 
     67   return results.Pass();
     68 }
     69 
     70 scoped_ptr<Database::MetricVector> NoAggregation::AggregateInterval(
     71     MetricType metric_type,
     72     Database::MetricVector::const_iterator* metric,
     73     const Database::MetricVector::const_iterator& metric_end,
     74     const base::Time& time_start,
     75     const base::Time& time_end,
     76     const base::TimeDelta& resolution) {
     77   scoped_ptr<Database::MetricVector> aggregated_series(
     78       new Database::MetricVector());
     79 
     80   for (; *metric != metric_end && (*metric)->time <= time_end; ++(*metric))
     81     aggregated_series->push_back(**metric);
     82 
     83   return aggregated_series.Pass();
     84 }
     85 
     86 scoped_ptr<Database::MetricVector> MedianAggregation::AggregateInterval(
     87     MetricType metric_type,
     88     Database::MetricVector::const_iterator* metric,
     89     const Database::MetricVector::const_iterator& metric_end,
     90     const base::Time& time_start,
     91     const base::Time& time_end,
     92     const base::TimeDelta& resolution) {
     93   scoped_ptr<Database::MetricVector> aggregated_series(
     94       new Database::MetricVector());
     95   base::Time window_start = time_start;
     96 
     97   while (*metric != metric_end && (*metric)->time <= time_end) {
     98     std::vector<double> values;
     99     while (*metric != metric_end &&
    100            (*metric)->time <= time_end &&
    101            (*metric)->time < window_start + resolution) {
    102       values.push_back((*metric)->value);
    103       ++(*metric);
    104     }
    105 
    106     if (!values.empty()) {
    107       aggregated_series->push_back(Metric(metric_type,
    108                                           window_start + resolution,
    109                                           SortAndGetMedian(&values)));
    110     }
    111     window_start += resolution;
    112   }
    113 
    114   return aggregated_series.Pass();
    115 }
    116 
    117 scoped_ptr<Database::MetricVector> MeanAggregation::AggregateInterval(
    118     MetricType metric_type,
    119     Database::MetricVector::const_iterator* metric,
    120     const Database::MetricVector::const_iterator& metric_end,
    121     const base::Time& time_start,
    122     const base::Time& time_end,
    123     const base::TimeDelta& resolution) {
    124   scoped_ptr<Database::MetricVector> aggregated_series(
    125       new Database::MetricVector());
    126 
    127   while (*metric != metric_end && (*metric)->time <= time_end) {
    128     // Finds the beginning of the next aggregation window.
    129     int64 window_offset = ((*metric)->time - time_start) / resolution;
    130     base::Time window_start = time_start + (window_offset * resolution);
    131     base::Time window_end = window_start + resolution;
    132     base::Time last_sample_time = window_start;
    133     double integrated = 0.0;
    134     double metric_value = 0.0;
    135 
    136     // Aggregate the step function defined by the Metrics in |metrics|.
    137     while (*metric != metric_end && (*metric)->time <= window_end) {
    138       metric_value = (*metric)->value;
    139       integrated += metric_value *
    140                     ((*metric)->time - last_sample_time).InSecondsF();
    141       last_sample_time = (*metric)->time;
    142       ++(*metric);
    143     }
    144     if (*metric != metric_end)
    145       metric_value = (*metric)->value;
    146 
    147     // If the window splits an area of the step function, split the
    148     // aggregation at the end of the window.
    149     integrated += metric_value * (window_end - last_sample_time).InSecondsF();
    150     double average = integrated / resolution.InSecondsF();
    151     aggregated_series->push_back(Metric(metric_type, window_end, average));
    152   }
    153 
    154   return aggregated_series.Pass();
    155 }
    156 
    157 double GetConversionFactor(UnitDetails from, UnitDetails to) {
    158   if (from.measurement_type != to.measurement_type) {
    159     LOG(ERROR) << "Invalid conversion requested";
    160     return 0.0;
    161   }
    162 
    163   return static_cast<double>(from.amount_in_base_units) /
    164       static_cast<double>(to.amount_in_base_units);
    165 }
    166 
    167 scoped_ptr<VectorOfMetricVectors> AggregateMetric(
    168     MetricType type,
    169     const Database::MetricVector* metrics,
    170     const base::Time& start,
    171     const std::vector<TimeRange>& intervals,
    172     const base::TimeDelta& resolution,
    173     AggregationMethod method) {
    174   if (!metrics || intervals.empty())
    175     return scoped_ptr<VectorOfMetricVectors>();
    176 
    177   CHECK(resolution > base::TimeDelta());
    178 
    179   switch (method) {
    180     case AGGREGATION_METHOD_NONE:
    181       return NoAggregation().AggregateMetrics(
    182           type, metrics, start, intervals, resolution);
    183     case AGGREGATION_METHOD_MEDIAN:
    184       return MedianAggregation().AggregateMetrics(
    185           type, metrics, start, intervals, resolution);
    186     case AGGREGATION_METHOD_MEAN:
    187       return MeanAggregation().AggregateMetrics(
    188           type, metrics, start, intervals, resolution);
    189     default:
    190       NOTREACHED();
    191       return scoped_ptr<VectorOfMetricVectors>();
    192   }
    193 }
    194 
    195 }  // namespace performance_monitor
    196