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