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