blob: 7dc267105ebd6284e20fba765335073761954849 [file] [log] [blame]
Elliott Hughes307f75d2011-10-12 18:04:40 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_SRC_TIMING_LOGGER_H_
18#define ART_SRC_TIMING_LOGGER_H_
19
20#include "logging.h"
21#include "utils.h"
22
Mathieu Chartier0325e622012-09-05 14:22:51 -070023#include <cmath>
Elliott Hughes307f75d2011-10-12 18:04:40 -070024#include <stdint.h>
Elliott Hughes307f75d2011-10-12 18:04:40 -070025#include <string>
26#include <vector>
27
28namespace art {
29
Mathieu Chartier0325e622012-09-05 14:22:51 -070030class CumulativeLogger;
31
Elliott Hughes307f75d2011-10-12 18:04:40 -070032class TimingLogger {
Elliott Hughesff17f1f2012-01-24 18:12:29 -080033 public:
Mathieu Chartier357e9be2012-08-01 11:00:14 -070034 explicit TimingLogger(const char* name, bool precise = false)
35 : name_(name), precise_(precise) {
Elliott Hughes307f75d2011-10-12 18:04:40 -070036 AddSplit("");
37 }
38
39 void AddSplit(const std::string& label) {
40 times_.push_back(NanoTime());
41 labels_.push_back(label);
42 }
43
Elliott Hughes73e66f72012-05-09 09:34:45 -070044 void Dump() const {
45 Dump(LOG(INFO));
Elliott Hughes601a1232012-02-02 17:47:38 -080046 }
47
Elliott Hughes73e66f72012-05-09 09:34:45 -070048 void Dump(std::ostream& os) const {
Mathieu Chartier0325e622012-09-05 14:22:51 -070049 uint64_t largest_time = 0;
Elliott Hughes4cb05682012-05-24 19:05:53 -070050 os << name_ << ": begin\n";
Elliott Hughes73e66f72012-05-09 09:34:45 -070051 for (size_t i = 1; i < times_.size(); ++i) {
Mathieu Chartier0325e622012-09-05 14:22:51 -070052 uint64_t delta_time = times_[i] - times_[i - 1];
53 largest_time = std::max(largest_time, delta_time);
54 }
55 // Compute which type of unit we will use for printing the timings.
56 TimeUnit tu = GetAppropriateTimeUnit(largest_time);
57 uint64_t divisor = GetNsToTimeUnitDivisor(tu);
58 for (size_t i = 1; i < times_.size(); ++i) {
59 uint64_t delta_time = times_[i] - times_[i - 1];
Mathieu Chartiere0f0cb32012-08-28 11:26:00 -070060 if (!precise_ && divisor >= 1000) {
Mathieu Chartier0325e622012-09-05 14:22:51 -070061 // Make the fraction 0.
Mathieu Chartiere0f0cb32012-08-28 11:26:00 -070062 delta_time -= delta_time % (divisor / 1000);
Mathieu Chartier357e9be2012-08-01 11:00:14 -070063 }
Mathieu Chartier0325e622012-09-05 14:22:51 -070064 os << name_ << ": " << std::setw(8) << FormatDuration(delta_time, tu) << " " << labels_[i]
65 << "\n";
Elliott Hughes73e66f72012-05-09 09:34:45 -070066 }
Elliott Hughes4cb05682012-05-24 19:05:53 -070067 os << name_ << ": end, " << NsToMs(GetTotalNs()) << " ms\n";
Elliott Hughes73e66f72012-05-09 09:34:45 -070068 }
69
70 uint64_t GetTotalNs() const {
Elliott Hughes601a1232012-02-02 17:47:38 -080071 return times_.back() - times_.front();
Elliott Hughes307f75d2011-10-12 18:04:40 -070072 }
73
Mathieu Chartier0325e622012-09-05 14:22:51 -070074 protected:
Elliott Hughes307f75d2011-10-12 18:04:40 -070075 std::string name_;
Mathieu Chartier357e9be2012-08-01 11:00:14 -070076 bool precise_;
Elliott Hughes307f75d2011-10-12 18:04:40 -070077 std::vector<uint64_t> times_;
78 std::vector<std::string> labels_;
Mathieu Chartier0325e622012-09-05 14:22:51 -070079
80 friend class CumulativeLogger;
81};
82
83class CumulativeLogger {
84 public:
85 explicit CumulativeLogger(const char* name = "", bool precise = false)
86 : name_(name),
Ian Rogers5f5a2c02012-09-17 10:52:08 -070087 precise_(precise) {
88 Reset();
Mathieu Chartier0325e622012-09-05 14:22:51 -070089 }
90
91 void Start() {
92 index_ = 0;
93 last_split_ = NanoTime();
94 }
95
96 void End() {
97 iterations_++;
98 }
99
100 void AddSplit(const std::string& label) {
101 uint64_t cur_time = NanoTime();
102 AddPair(label, cur_time - last_split_);
103 last_split_ = cur_time;
104 }
105
106 void Reset() {
Mathieu Chartier0325e622012-09-05 14:22:51 -0700107 times_.clear();
108 labels_.clear();
109 times_squared_.clear();
Ian Rogers5f5a2c02012-09-17 10:52:08 -0700110 iterations_ = 0;
111 total_time_squared_ = 0;
Mathieu Chartier0325e622012-09-05 14:22:51 -0700112 }
113
114 void AddPair(const std::string& label, uint64_t delta_time) {
115 // Convert delta time to microseconds so that we don't overflow our counters.
116 delta_time /= kAdjust;
117 if (index_ >= times_.size()) {
118 times_.push_back(delta_time);
119 times_squared_.push_back(delta_time * delta_time);
120 labels_.push_back(label);
121 } else {
122 times_[index_] += delta_time;
123 times_squared_[index_] += delta_time * delta_time;
124 DCHECK_EQ(labels_[index_], label);
125 }
126 index_++;
127 }
128
129 void AddLogger(const TimingLogger& logger) {
130 DCHECK_EQ(logger.times_.size(), logger.labels_.size());
131 uint64_t total_time = 0;
132 for (size_t i = 1; i < logger.times_.size(); ++i) {
133 const uint64_t delta_time = logger.times_[i] - logger.times_[i - 1];
134 const std::string& label = logger.labels_[i];
135 AddPair(label, delta_time);
136 total_time += delta_time;
137 }
138 total_time /= kAdjust;
139 total_time_squared_ += total_time * total_time;
140 }
141
142 void Dump() const {
143 Dump(LOG(INFO));
144 }
145
146 void Dump(std::ostream& os) const {
147 os << name_ << ": iterations " << iterations_ << " begin\n";
148 //Find which unit we will use for the timing logger.
149 uint64_t largest_mean = 0;
150 for (size_t i = 0; i < times_.size(); ++i) {
151 // Convert back to nanoseconds from microseconds.
152 uint64_t mean = times_[i] / iterations_;
153 largest_mean = std::max(largest_mean, mean);
154 }
155 // Convert largest mean back to ns
156 TimeUnit tu = GetAppropriateTimeUnit(largest_mean * kAdjust);
157 uint64_t divisor = GetNsToTimeUnitDivisor(tu);
158 for (size_t i = 0; i < times_.size(); ++i) {
159 uint64_t mean_x2 = times_squared_[i] / iterations_;
160 uint64_t mean = times_[i] / iterations_;
161 uint64_t variance = mean_x2 - (mean * mean);
162 uint64_t std_dev = static_cast<uint64_t>(std::sqrt(static_cast<double>(variance)));
Mathieu Chartiere0f0cb32012-08-28 11:26:00 -0700163 if (!precise_ && divisor >= 1000) {
Mathieu Chartier0325e622012-09-05 14:22:51 -0700164 // Make the fraction 0.
Mathieu Chartiere0f0cb32012-08-28 11:26:00 -0700165 mean -= mean % (divisor / 1000);
166 std_dev -= std_dev % (divisor / 1000);
Mathieu Chartier0325e622012-09-05 14:22:51 -0700167 }
168 os << name_ << ": " << std::setw(8)
169 << FormatDuration(mean * kAdjust, tu) << " std_dev "
170 << FormatDuration(std_dev * kAdjust, tu) << " " << labels_[i] << "\n";
171 }
172 uint64_t total_mean_x2 = total_time_squared_;
Mathieu Chartier155dfe92012-10-09 14:24:49 -0700173 uint64_t mean_total_ns = GetTotalTime();
Mathieu Chartier0325e622012-09-05 14:22:51 -0700174 if (iterations_ != 0) {
175 total_mean_x2 /= iterations_;
176 mean_total_ns /= iterations_;
177 }
178 uint64_t total_variance = total_mean_x2 - (mean_total_ns * mean_total_ns);
179 uint64_t total_std_dev = static_cast<uint64_t>(
180 std::sqrt(static_cast<double>(total_variance)));
181 os << name_ << ": end, mean " << PrettyDuration(mean_total_ns * kAdjust)
182 << " std_dev " << PrettyDuration(total_std_dev * kAdjust) << "\n";
183 }
184
185 uint64_t GetTotalNs() const {
Mathieu Chartier155dfe92012-10-09 14:24:49 -0700186 return GetTotalTime() * kAdjust;
187 }
188
189 private:
190
191 uint64_t GetTotalTime() const {
Mathieu Chartier0325e622012-09-05 14:22:51 -0700192 uint64_t total = 0;
193 for (size_t i = 0; i < times_.size(); ++i) {
194 total += times_[i];
195 }
196 return total;
197 }
198
Mathieu Chartier0325e622012-09-05 14:22:51 -0700199 static const uint64_t kAdjust = 1000;
200 std::string name_;
201 bool precise_;
202 uint64_t total_time_squared_;
203 std::vector<uint64_t> times_;
204 std::vector<uint64_t> times_squared_;
205 std::vector<std::string> labels_;
206 size_t index_;
207 size_t iterations_;
208 uint64_t last_split_;
Elliott Hughes307f75d2011-10-12 18:04:40 -0700209};
210
211} // namespace art
212
213#endif // ART_SRC_TIMING_LOGGER_H_