1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/stats_counters.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,257 @@ 1.4 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 + 1.9 +#ifndef BASE_STATS_COUNTERS_H__ 1.10 +#define BASE_STATS_COUNTERS_H__ 1.11 + 1.12 +#include <string> 1.13 +#include "base/stats_table.h" 1.14 +#include "base/time.h" 1.15 + 1.16 +// StatsCounters are dynamically created values which can be tracked in 1.17 +// the StatsTable. They are designed to be lightweight to create and 1.18 +// easy to use. 1.19 +// 1.20 +// Since StatsCounters can be created dynamically by name, there is 1.21 +// a hash table lookup to find the counter in the table. A StatsCounter 1.22 +// object can be created once and used across multiple threads safely. 1.23 +// 1.24 +// Example usage: 1.25 +// { 1.26 +// StatsCounter request_count("RequestCount"); 1.27 +// request_count.Increment(); 1.28 +// } 1.29 +// 1.30 +// Note that creating counters on the stack does work, however creating 1.31 +// the counter object requires a hash table lookup. For inner loops, it 1.32 +// may be better to create the counter either as a member of another object 1.33 +// (or otherwise outside of the loop) for maximum performance. 1.34 +// 1.35 +// Internally, a counter represents a value in a row of a StatsTable. 1.36 +// The row has a 32bit value for each process/thread in the table and also 1.37 +// a name (stored in the table metadata). 1.38 +// 1.39 +// NOTE: In order to make stats_counters usable in lots of different code, 1.40 +// avoid any dependencies inside this header file. 1.41 +// 1.42 + 1.43 +//------------------------------------------------------------------------------ 1.44 +// Define macros for ease of use. They also allow us to change definitions 1.45 +// as the implementation varies, or depending on compile options. 1.46 +//------------------------------------------------------------------------------ 1.47 +// First provide generic macros, which exist in production as well as debug. 1.48 +#define STATS_COUNTER(name, delta) do { \ 1.49 + static StatsCounter counter(name); \ 1.50 + counter.Add(delta); \ 1.51 +} while (0) 1.52 + 1.53 +#define SIMPLE_STATS_COUNTER(name) STATS_COUNTER(name, 1) 1.54 + 1.55 +#define RATE_COUNTER(name, duration) do { \ 1.56 + static StatsRate hit_count(name); \ 1.57 + hit_count.AddTime(duration); \ 1.58 +} while (0) 1.59 + 1.60 +// Define Debug vs non-debug flavors of macros. 1.61 +#ifndef NDEBUG 1.62 + 1.63 +#define DSTATS_COUNTER(name, delta) STATS_COUNTER(name, delta) 1.64 +#define DSIMPLE_STATS_COUNTER(name) SIMPLE_STATS_COUNTER(name) 1.65 +#define DRATE_COUNTER(name, duration) RATE_COUNTER(name, duration) 1.66 + 1.67 +#else // NDEBUG 1.68 + 1.69 +#define DSTATS_COUNTER(name, delta) do {} while (0) 1.70 +#define DSIMPLE_STATS_COUNTER(name) do {} while (0) 1.71 +#define DRATE_COUNTER(name, duration) do {} while (0) 1.72 + 1.73 +#endif // NDEBUG 1.74 + 1.75 +//------------------------------------------------------------------------------ 1.76 +// StatsCounter represents a counter in the StatsTable class. 1.77 +class StatsCounter { 1.78 + public: 1.79 + // Create a StatsCounter object. 1.80 + explicit StatsCounter(const std::string& name) 1.81 + : counter_id_(-1) { 1.82 + // We prepend the name with 'c:' to indicate that it is a counter. 1.83 + name_ = "c:"; 1.84 + name_.append(name); 1.85 + }; 1.86 + 1.87 + virtual ~StatsCounter() {} 1.88 + 1.89 + // Sets the counter to a specific value. 1.90 + void Set(int value) { 1.91 + int* loc = GetPtr(); 1.92 + if (loc) *loc = value; 1.93 + } 1.94 + 1.95 + // Increments the counter. 1.96 + void Increment() { 1.97 + Add(1); 1.98 + } 1.99 + 1.100 + virtual void Add(int value) { 1.101 + int* loc = GetPtr(); 1.102 + if (loc) 1.103 + (*loc) += value; 1.104 + } 1.105 + 1.106 + // Decrements the counter. 1.107 + void Decrement() { 1.108 + Add(-1); 1.109 + } 1.110 + 1.111 + void Subtract(int value) { 1.112 + Add(-value); 1.113 + } 1.114 + 1.115 + // Is this counter enabled? 1.116 + // Returns false if table is full. 1.117 + bool Enabled() { 1.118 + return GetPtr() != NULL; 1.119 + } 1.120 + 1.121 + int value() { 1.122 + int* loc = GetPtr(); 1.123 + if (loc) return *loc; 1.124 + return 0; 1.125 + } 1.126 + 1.127 + protected: 1.128 + StatsCounter() 1.129 + : counter_id_(-1) { 1.130 + } 1.131 + 1.132 + // Returns the cached address of this counter location. 1.133 + int* GetPtr() { 1.134 + StatsTable* table = StatsTable::current(); 1.135 + if (!table) 1.136 + return NULL; 1.137 + 1.138 + // If counter_id_ is -1, then we haven't looked it up yet. 1.139 + if (counter_id_ == -1) { 1.140 + counter_id_ = table->FindCounter(name_); 1.141 + if (table->GetSlot() == 0) { 1.142 + if (!table->RegisterThread("")) { 1.143 + // There is no room for this thread. This thread 1.144 + // cannot use counters. 1.145 + counter_id_ = 0; 1.146 + return NULL; 1.147 + } 1.148 + } 1.149 + } 1.150 + 1.151 + // If counter_id_ is > 0, then we have a valid counter. 1.152 + if (counter_id_ > 0) 1.153 + return table->GetLocation(counter_id_, table->GetSlot()); 1.154 + 1.155 + // counter_id_ was zero, which means the table is full. 1.156 + return NULL; 1.157 + } 1.158 + 1.159 + std::string name_; 1.160 + // The counter id in the table. We initialize to -1 (an invalid value) 1.161 + // and then cache it once it has been looked up. The counter_id is 1.162 + // valid across all threads and processes. 1.163 + int32_t counter_id_; 1.164 +}; 1.165 + 1.166 + 1.167 +// A StatsCounterTimer is a StatsCounter which keeps a timer during 1.168 +// the scope of the StatsCounterTimer. On destruction, it will record 1.169 +// its time measurement. 1.170 +class StatsCounterTimer : protected StatsCounter { 1.171 + public: 1.172 + // Constructs and starts the timer. 1.173 + explicit StatsCounterTimer(const std::string& name) { 1.174 + // we prepend the name with 't:' to indicate that it is a timer. 1.175 + name_ = "t:"; 1.176 + name_.append(name); 1.177 + } 1.178 + 1.179 + // Start the timer. 1.180 + void Start() { 1.181 + if (!Enabled()) 1.182 + return; 1.183 + start_time_ = base::TimeTicks::Now(); 1.184 + stop_time_ = base::TimeTicks(); 1.185 + } 1.186 + 1.187 + // Stop the timer and record the results. 1.188 + void Stop() { 1.189 + if (!Enabled() || !Running()) 1.190 + return; 1.191 + stop_time_ = base::TimeTicks::Now(); 1.192 + Record(); 1.193 + } 1.194 + 1.195 + // Returns true if the timer is running. 1.196 + bool Running() { 1.197 + return Enabled() && !start_time_.is_null() && stop_time_.is_null(); 1.198 + } 1.199 + 1.200 + // Accept a TimeDelta to increment. 1.201 + virtual void AddTime(base::TimeDelta time) { 1.202 + Add(static_cast<int>(time.InMilliseconds())); 1.203 + } 1.204 + 1.205 + protected: 1.206 + // Compute the delta between start and stop, in milliseconds. 1.207 + void Record() { 1.208 + AddTime(stop_time_ - start_time_); 1.209 + } 1.210 + 1.211 + base::TimeTicks start_time_; 1.212 + base::TimeTicks stop_time_; 1.213 +}; 1.214 + 1.215 +// A StatsRate is a timer that keeps a count of the number of intervals added so 1.216 +// that several statistics can be produced: 1.217 +// min, max, avg, count, total 1.218 +class StatsRate : public StatsCounterTimer { 1.219 + public: 1.220 + // Constructs and starts the timer. 1.221 + explicit StatsRate(const char* name) 1.222 + : StatsCounterTimer(name), 1.223 + counter_(name), 1.224 + largest_add_(std::string(" ").append(name).append("MAX").c_str()) { 1.225 + } 1.226 + 1.227 + virtual void Add(int value) { 1.228 + counter_.Increment(); 1.229 + StatsCounterTimer::Add(value); 1.230 + if (value > largest_add_.value()) 1.231 + largest_add_.Set(value); 1.232 + } 1.233 + 1.234 + private: 1.235 + StatsCounter counter_; 1.236 + StatsCounter largest_add_; 1.237 +}; 1.238 + 1.239 + 1.240 +// Helper class for scoping a timer or rate. 1.241 +template<class T> class StatsScope { 1.242 + public: 1.243 + explicit StatsScope<T>(T& timer) 1.244 + : timer_(timer) { 1.245 + timer_.Start(); 1.246 + } 1.247 + 1.248 + ~StatsScope() { 1.249 + timer_.Stop(); 1.250 + } 1.251 + 1.252 + void Stop() { 1.253 + timer_.Stop(); 1.254 + } 1.255 + 1.256 + private: 1.257 + T& timer_; 1.258 +}; 1.259 + 1.260 +#endif // BASE_STATS_COUNTERS_H__