ipc/chromium/src/base/stats_counters.h

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:cadb80945ad7
1 // Copyright (c) 2006-2008 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
6 #ifndef BASE_STATS_COUNTERS_H__
7 #define BASE_STATS_COUNTERS_H__
8
9 #include <string>
10 #include "base/stats_table.h"
11 #include "base/time.h"
12
13 // StatsCounters are dynamically created values which can be tracked in
14 // the StatsTable. They are designed to be lightweight to create and
15 // easy to use.
16 //
17 // Since StatsCounters can be created dynamically by name, there is
18 // a hash table lookup to find the counter in the table. A StatsCounter
19 // object can be created once and used across multiple threads safely.
20 //
21 // Example usage:
22 // {
23 // StatsCounter request_count("RequestCount");
24 // request_count.Increment();
25 // }
26 //
27 // Note that creating counters on the stack does work, however creating
28 // the counter object requires a hash table lookup. For inner loops, it
29 // may be better to create the counter either as a member of another object
30 // (or otherwise outside of the loop) for maximum performance.
31 //
32 // Internally, a counter represents a value in a row of a StatsTable.
33 // The row has a 32bit value for each process/thread in the table and also
34 // a name (stored in the table metadata).
35 //
36 // NOTE: In order to make stats_counters usable in lots of different code,
37 // avoid any dependencies inside this header file.
38 //
39
40 //------------------------------------------------------------------------------
41 // Define macros for ease of use. They also allow us to change definitions
42 // as the implementation varies, or depending on compile options.
43 //------------------------------------------------------------------------------
44 // First provide generic macros, which exist in production as well as debug.
45 #define STATS_COUNTER(name, delta) do { \
46 static StatsCounter counter(name); \
47 counter.Add(delta); \
48 } while (0)
49
50 #define SIMPLE_STATS_COUNTER(name) STATS_COUNTER(name, 1)
51
52 #define RATE_COUNTER(name, duration) do { \
53 static StatsRate hit_count(name); \
54 hit_count.AddTime(duration); \
55 } while (0)
56
57 // Define Debug vs non-debug flavors of macros.
58 #ifndef NDEBUG
59
60 #define DSTATS_COUNTER(name, delta) STATS_COUNTER(name, delta)
61 #define DSIMPLE_STATS_COUNTER(name) SIMPLE_STATS_COUNTER(name)
62 #define DRATE_COUNTER(name, duration) RATE_COUNTER(name, duration)
63
64 #else // NDEBUG
65
66 #define DSTATS_COUNTER(name, delta) do {} while (0)
67 #define DSIMPLE_STATS_COUNTER(name) do {} while (0)
68 #define DRATE_COUNTER(name, duration) do {} while (0)
69
70 #endif // NDEBUG
71
72 //------------------------------------------------------------------------------
73 // StatsCounter represents a counter in the StatsTable class.
74 class StatsCounter {
75 public:
76 // Create a StatsCounter object.
77 explicit StatsCounter(const std::string& name)
78 : counter_id_(-1) {
79 // We prepend the name with 'c:' to indicate that it is a counter.
80 name_ = "c:";
81 name_.append(name);
82 };
83
84 virtual ~StatsCounter() {}
85
86 // Sets the counter to a specific value.
87 void Set(int value) {
88 int* loc = GetPtr();
89 if (loc) *loc = value;
90 }
91
92 // Increments the counter.
93 void Increment() {
94 Add(1);
95 }
96
97 virtual void Add(int value) {
98 int* loc = GetPtr();
99 if (loc)
100 (*loc) += value;
101 }
102
103 // Decrements the counter.
104 void Decrement() {
105 Add(-1);
106 }
107
108 void Subtract(int value) {
109 Add(-value);
110 }
111
112 // Is this counter enabled?
113 // Returns false if table is full.
114 bool Enabled() {
115 return GetPtr() != NULL;
116 }
117
118 int value() {
119 int* loc = GetPtr();
120 if (loc) return *loc;
121 return 0;
122 }
123
124 protected:
125 StatsCounter()
126 : counter_id_(-1) {
127 }
128
129 // Returns the cached address of this counter location.
130 int* GetPtr() {
131 StatsTable* table = StatsTable::current();
132 if (!table)
133 return NULL;
134
135 // If counter_id_ is -1, then we haven't looked it up yet.
136 if (counter_id_ == -1) {
137 counter_id_ = table->FindCounter(name_);
138 if (table->GetSlot() == 0) {
139 if (!table->RegisterThread("")) {
140 // There is no room for this thread. This thread
141 // cannot use counters.
142 counter_id_ = 0;
143 return NULL;
144 }
145 }
146 }
147
148 // If counter_id_ is > 0, then we have a valid counter.
149 if (counter_id_ > 0)
150 return table->GetLocation(counter_id_, table->GetSlot());
151
152 // counter_id_ was zero, which means the table is full.
153 return NULL;
154 }
155
156 std::string name_;
157 // The counter id in the table. We initialize to -1 (an invalid value)
158 // and then cache it once it has been looked up. The counter_id is
159 // valid across all threads and processes.
160 int32_t counter_id_;
161 };
162
163
164 // A StatsCounterTimer is a StatsCounter which keeps a timer during
165 // the scope of the StatsCounterTimer. On destruction, it will record
166 // its time measurement.
167 class StatsCounterTimer : protected StatsCounter {
168 public:
169 // Constructs and starts the timer.
170 explicit StatsCounterTimer(const std::string& name) {
171 // we prepend the name with 't:' to indicate that it is a timer.
172 name_ = "t:";
173 name_.append(name);
174 }
175
176 // Start the timer.
177 void Start() {
178 if (!Enabled())
179 return;
180 start_time_ = base::TimeTicks::Now();
181 stop_time_ = base::TimeTicks();
182 }
183
184 // Stop the timer and record the results.
185 void Stop() {
186 if (!Enabled() || !Running())
187 return;
188 stop_time_ = base::TimeTicks::Now();
189 Record();
190 }
191
192 // Returns true if the timer is running.
193 bool Running() {
194 return Enabled() && !start_time_.is_null() && stop_time_.is_null();
195 }
196
197 // Accept a TimeDelta to increment.
198 virtual void AddTime(base::TimeDelta time) {
199 Add(static_cast<int>(time.InMilliseconds()));
200 }
201
202 protected:
203 // Compute the delta between start and stop, in milliseconds.
204 void Record() {
205 AddTime(stop_time_ - start_time_);
206 }
207
208 base::TimeTicks start_time_;
209 base::TimeTicks stop_time_;
210 };
211
212 // A StatsRate is a timer that keeps a count of the number of intervals added so
213 // that several statistics can be produced:
214 // min, max, avg, count, total
215 class StatsRate : public StatsCounterTimer {
216 public:
217 // Constructs and starts the timer.
218 explicit StatsRate(const char* name)
219 : StatsCounterTimer(name),
220 counter_(name),
221 largest_add_(std::string(" ").append(name).append("MAX").c_str()) {
222 }
223
224 virtual void Add(int value) {
225 counter_.Increment();
226 StatsCounterTimer::Add(value);
227 if (value > largest_add_.value())
228 largest_add_.Set(value);
229 }
230
231 private:
232 StatsCounter counter_;
233 StatsCounter largest_add_;
234 };
235
236
237 // Helper class for scoping a timer or rate.
238 template<class T> class StatsScope {
239 public:
240 explicit StatsScope<T>(T& timer)
241 : timer_(timer) {
242 timer_.Start();
243 }
244
245 ~StatsScope() {
246 timer_.Stop();
247 }
248
249 void Stop() {
250 timer_.Stop();
251 }
252
253 private:
254 T& timer_;
255 };
256
257 #endif // BASE_STATS_COUNTERS_H__

mercurial