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