15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_METRICS_STATS_COUNTERS_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_METRICS_STATS_COUNTERS_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_export.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/stats_table.h" 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// StatsCounters are dynamically created values which can be tracked in 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the StatsTable. They are designed to be lightweight to create and 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// easy to use. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Since StatsCounters can be created dynamically by name, there is 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a hash table lookup to find the counter in the table. A StatsCounter 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// object can be created once and used across multiple threads safely. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Example usage: 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// StatsCounter request_count("RequestCount"); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// request_count.Increment(); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// } 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that creating counters on the stack does work, however creating 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the counter object requires a hash table lookup. For inner loops, it 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// may be better to create the counter either as a member of another object 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (or otherwise outside of the loop) for maximum performance. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Internally, a counter represents a value in a row of a StatsTable. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The row has a 32bit value for each process/thread in the table and also 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a name (stored in the table metadata). 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: In order to make stats_counters usable in lots of different code, 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// avoid any dependencies inside this header file. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Define macros for ease of use. They also allow us to change definitions 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as the implementation varies, or depending on compile options. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// First provide generic macros, which exist in production as well as debug. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define STATS_COUNTER(name, delta) do { \ 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StatsCounter counter(name); \ 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) counter.Add(delta); \ 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SIMPLE_STATS_COUNTER(name) STATS_COUNTER(name, 1) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RATE_COUNTER(name, duration) do { \ 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StatsRate hit_count(name); \ 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hit_count.AddTime(duration); \ 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Define Debug vs non-debug flavors of macros. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DSTATS_COUNTER(name, delta) STATS_COUNTER(name, delta) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DSIMPLE_STATS_COUNTER(name) SIMPLE_STATS_COUNTER(name) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DRATE_COUNTER(name, duration) RATE_COUNTER(name, duration) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else // NDEBUG 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DSTATS_COUNTER(name, delta) do {} while (0) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DSIMPLE_STATS_COUNTER(name) do {} while (0) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DRATE_COUNTER(name, duration) do {} while (0) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // NDEBUG 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// StatsCounter represents a counter in the StatsTable class. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT StatsCounter { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a StatsCounter object. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit StatsCounter(const std::string& name); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~StatsCounter(); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the counter to a specific value. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Set(int value); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Increments the counter. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Increment() { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Add(1); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Add(int value); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Decrements the counter. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Decrement() { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Add(-1); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Subtract(int value) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Add(-value); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Is this counter enabled? 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns false if table is full. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Enabled() { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetPtr() != NULL; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int value() { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* loc = GetPtr(); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (loc) return *loc; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StatsCounter(); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the cached address of this counter location. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* GetPtr(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string name_; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The counter id in the table. We initialize to -1 (an invalid value) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and then cache it once it has been looked up. The counter_id is 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // valid across all threads and processes. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 counter_id_; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A StatsCounterTimer is a StatsCounter which keeps a timer during 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the scope of the StatsCounterTimer. On destruction, it will record 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// its time measurement. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT StatsCounterTimer : protected StatsCounter { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Constructs and starts the timer. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit StatsCounterTimer(const std::string& name); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~StatsCounterTimer(); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start the timer. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Start(); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stop the timer and record the results. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Stop(); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if the timer is running. 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Running(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Accept a TimeDelta to increment. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void AddTime(TimeDelta time); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compute the delta between start and stop, in milliseconds. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Record(); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks start_time_; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks stop_time_; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A StatsRate is a timer that keeps a count of the number of intervals added so 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that several statistics can be produced: 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// min, max, avg, count, total 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT StatsRate : public StatsCounterTimer { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Constructs and starts the timer. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit StatsRate(const std::string& name); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~StatsRate(); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Add(int value) OVERRIDE; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StatsCounter counter_; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StatsCounter largest_add_; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper class for scoping a timer or rate. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class T> class StatsScope { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit StatsScope<T>(T& timer) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : timer_(timer) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_.Start(); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~StatsScope() { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_.Stop(); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Stop() { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_.Stop(); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T& timer_; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // BASE_METRICS_STATS_COUNTERS_H_ 198