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 8#include <string> 9 10#include "base/base_export.h" 11#include "base/compiler_specific.h" 12#include "base/metrics/stats_table.h" 13#include "base/time/time.h" 14 15namespace 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. 78class BASE_EXPORT 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. 88 void Increment() { 89 Add(1); 90 } 91 92 virtual void Add(int value); 93 94 // Decrements the counter. 95 void Decrement() { 96 Add(-1); 97 } 98 99 void Subtract(int value) { 100 Add(-value); 101 } 102 103 // Is this counter enabled? 104 // Returns false if table is full. 105 bool Enabled() { 106 return GetPtr() != NULL; 107 } 108 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. 132class BASE_EXPORT 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 161class BASE_EXPORT 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) OVERRIDE; 168 169 private: 170 StatsCounter counter_; 171 StatsCounter largest_add_; 172}; 173 174 175// Helper class for scoping a timer or rate. 176template<class T> class StatsScope { 177 public: 178 explicit StatsScope<T>(T& timer) 179 : timer_(timer) { 180 timer_.Start(); 181 } 182 183 ~StatsScope() { 184 timer_.Stop(); 185 } 186 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