• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 #ifndef BASE_METRICS_STATS_COUNTERS_H_
6 #define BASE_METRICS_STATS_COUNTERS_H_
7 #pragma once
8 
9 #include <string>
10 
11 #include "base/base_api.h"
12 #include "base/metrics/stats_table.h"
13 #include "base/time.h"
14 
15 namespace base {
16 
17 // StatsCounters are dynamically created values which can be tracked in
18 // the StatsTable.  They are designed to be lightweight to create and
19 // easy to use.
20 //
21 // Since StatsCounters can be created dynamically by name, there is
22 // a hash table lookup to find the counter in the table.  A StatsCounter
23 // object can be created once and used across multiple threads safely.
24 //
25 // Example usage:
26 //    {
27 //      StatsCounter request_count("RequestCount");
28 //      request_count.Increment();
29 //    }
30 //
31 // Note that creating counters on the stack does work, however creating
32 // the counter object requires a hash table lookup.  For inner loops, it
33 // may be better to create the counter either as a member of another object
34 // (or otherwise outside of the loop) for maximum performance.
35 //
36 // Internally, a counter represents a value in a row of a StatsTable.
37 // The row has a 32bit value for each process/thread in the table and also
38 // a name (stored in the table metadata).
39 //
40 // NOTE: In order to make stats_counters usable in lots of different code,
41 // avoid any dependencies inside this header file.
42 //
43 
44 //------------------------------------------------------------------------------
45 // Define macros for ease of use. They also allow us to change definitions
46 // as the implementation varies, or depending on compile options.
47 //------------------------------------------------------------------------------
48 // First provide generic macros, which exist in production as well as debug.
49 #define STATS_COUNTER(name, delta) do { \
50   base::StatsCounter counter(name); \
51   counter.Add(delta); \
52 } while (0)
53 
54 #define SIMPLE_STATS_COUNTER(name) STATS_COUNTER(name, 1)
55 
56 #define RATE_COUNTER(name, duration) do { \
57   base::StatsRate hit_count(name); \
58   hit_count.AddTime(duration); \
59 } while (0)
60 
61 // Define Debug vs non-debug flavors of macros.
62 #ifndef NDEBUG
63 
64 #define DSTATS_COUNTER(name, delta) STATS_COUNTER(name, delta)
65 #define DSIMPLE_STATS_COUNTER(name) SIMPLE_STATS_COUNTER(name)
66 #define DRATE_COUNTER(name, duration) RATE_COUNTER(name, duration)
67 
68 #else  // NDEBUG
69 
70 #define DSTATS_COUNTER(name, delta) do {} while (0)
71 #define DSIMPLE_STATS_COUNTER(name) do {} while (0)
72 #define DRATE_COUNTER(name, duration) do {} while (0)
73 
74 #endif  // NDEBUG
75 
76 //------------------------------------------------------------------------------
77 // StatsCounter represents a counter in the StatsTable class.
78 class BASE_API StatsCounter {
79  public:
80   // Create a StatsCounter object.
81   explicit StatsCounter(const std::string& name);
82   virtual ~StatsCounter();
83 
84   // Sets the counter to a specific value.
85   void Set(int value);
86 
87   // Increments the counter.
Increment()88   void Increment() {
89     Add(1);
90   }
91 
92   virtual void Add(int value);
93 
94   // Decrements the counter.
Decrement()95   void Decrement() {
96     Add(-1);
97   }
98 
Subtract(int value)99   void Subtract(int value) {
100     Add(-value);
101   }
102 
103   // Is this counter enabled?
104   // Returns false if table is full.
Enabled()105   bool Enabled() {
106     return GetPtr() != NULL;
107   }
108 
value()109   int value() {
110     int* loc = GetPtr();
111     if (loc) return *loc;
112     return 0;
113   }
114 
115  protected:
116   StatsCounter();
117 
118   // Returns the cached address of this counter location.
119   int* GetPtr();
120 
121   std::string name_;
122   // The counter id in the table.  We initialize to -1 (an invalid value)
123   // and then cache it once it has been looked up.  The counter_id is
124   // valid across all threads and processes.
125   int32 counter_id_;
126 };
127 
128 
129 // A StatsCounterTimer is a StatsCounter which keeps a timer during
130 // the scope of the StatsCounterTimer.  On destruction, it will record
131 // its time measurement.
132 class BASE_API StatsCounterTimer : protected StatsCounter {
133  public:
134   // Constructs and starts the timer.
135   explicit StatsCounterTimer(const std::string& name);
136   virtual ~StatsCounterTimer();
137 
138   // Start the timer.
139   void Start();
140 
141   // Stop the timer and record the results.
142   void Stop();
143 
144   // Returns true if the timer is running.
145   bool Running();
146 
147   // Accept a TimeDelta to increment.
148   virtual void AddTime(TimeDelta time);
149 
150  protected:
151   // Compute the delta between start and stop, in milliseconds.
152   void Record();
153 
154   TimeTicks start_time_;
155   TimeTicks stop_time_;
156 };
157 
158 // A StatsRate is a timer that keeps a count of the number of intervals added so
159 // that several statistics can be produced:
160 //    min, max, avg, count, total
161 class BASE_API StatsRate : public StatsCounterTimer {
162  public:
163   // Constructs and starts the timer.
164   explicit StatsRate(const std::string& name);
165   virtual ~StatsRate();
166 
167   virtual void Add(int value);
168 
169  private:
170   StatsCounter counter_;
171   StatsCounter largest_add_;
172 };
173 
174 
175 // Helper class for scoping a timer or rate.
176 template<class T> class StatsScope {
177  public:
178   explicit StatsScope<T>(T& timer)
timer_(timer)179       : timer_(timer) {
180     timer_.Start();
181   }
182 
~StatsScope()183   ~StatsScope() {
184     timer_.Stop();
185   }
186 
Stop()187   void Stop() {
188     timer_.Stop();
189   }
190 
191  private:
192   T& timer_;
193 };
194 
195 }  // namespace base
196 
197 #endif  // BASE_METRICS_STATS_COUNTERS_H_
198