Home | History | Annotate | Download | only in metrics
      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.
     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.
    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)
    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