diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 21:49:38 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 21:49:38 +0000 |
commit | d7cae12696b96500c05dd2d430f6238922c20c96 (patch) | |
tree | ecff27b367735535b2a66477f8cd89d3c462a6c0 /base/stats_counters.h | |
parent | ee2815e28d408216cf94e874825b6bcf76c69083 (diff) | |
download | chromium_src-d7cae12696b96500c05dd2d430f6238922c20c96.zip chromium_src-d7cae12696b96500c05dd2d430f6238922c20c96.tar.gz chromium_src-d7cae12696b96500c05dd2d430f6238922c20c96.tar.bz2 |
Add base to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/stats_counters.h')
-rw-r--r-- | base/stats_counters.h | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/base/stats_counters.h b/base/stats_counters.h new file mode 100644 index 0000000..778b824 --- /dev/null +++ b/base/stats_counters.h @@ -0,0 +1,297 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#ifndef BASE_STATS_COUNTERS_H__ +#define BASE_STATS_COUNTERS_H__ + +#include <string> +#include "base/stats_table.h" +#include "base/time.h" + +// StatsCounters are dynamically created values which can be tracked in +// the StatsTable. They are designed to be lightweight to create and +// easy to use. +// +// Since StatsCounters can be created dynamically by name, there is +// a hash table lookup to find the counter in the table. A StatsCounter +// object can be created once and used across multiple threads safely. +// +// Example usage: +// { +// StatsCounter request_count("RequestCount"); +// request_count.Increment(); +// } +// +// Note that creating counters on the stack does work, however creating +// the counter object requires a hash table lookup. For inner loops, it +// may be better to create the counter either as a member of another object +// (or otherwise outside of the loop) for maximum performance. +// +// Internally, a counter represents a value in a row of a StatsTable. +// The row has a 32bit value for each process/thread in the table and also +// a name (stored in the table metadata). +// +// NOTE: In order to make stats_counters usable in lots of different code, +// avoid any dependencies inside this header file. +// + +//------------------------------------------------------------------------------ +// Define macros for ease of use. They also allow us to change definitions +// as the implementation varies, or depending on compile options. +//------------------------------------------------------------------------------ +// First provide generic macros, which exist in production as well as debug. +#define STATS_COUNTER(name, delta) do { \ + static StatsCounter counter(name); \ + counter.Add(delta); \ +} while (0) + +#define SIMPLE_STATS_COUNTER(name) STATS_COUNTER(name, 1) + +#define RATE_COUNTER(name, duration) do { \ + static StatsRate hit_count(name); \ + hit_count.AddTime(duration); \ +} while (0) + +// Define Debug vs non-debug flavors of macros. +#ifndef NDEBUG + +#define DSTATS_COUNTER(name, delta) STATS_COUNTER(name, delta) +#define DSIMPLE_STATS_COUNTER(name) SIMPLE_STATS_COUNTER(name) +#define DRATE_COUNTER(name, duration) RATE_COUNTER(name, duration) + +#else // NDEBUG + +#define DSTATS_COUNTER(name, delta) do {} while (0) +#define DSIMPLE_STATS_COUNTER(name) do {} while (0) +#define DRATE_COUNTER(name, duration) do {} while (0) + +#endif // NDEBUG + +//------------------------------------------------------------------------------ +// StatsCounter represents a counter in the StatsTable class. +class StatsCounter { + public: + // Create a StatsCounter object. + explicit StatsCounter(const std::wstring& name) + : counter_id_(-1) { + // We prepend the name with 'c:' to indicate that it is a counter. + name_ = L"c:"; + name_.append(name); + }; + + virtual ~StatsCounter() {} + + // Sets the counter to a specific value. + void Set(int value) { + int* loc = GetPtr(); + if (loc) *loc = value; + } + + // Increments the counter. + void Increment() { + Add(1); + } + + // TODO(jar) temporary hack include method till base and chrome use new name. + void Increment(int value) { + Add(value); + } + + virtual void Add(int value) { + int* loc = GetPtr(); + if (loc) + (*loc) += value; + } + + // Decrements the counter. + void Decrement() { + Add(-1); + } + + void Subtract(int value) { + Add(-value); + } + + // TODO(jar) temporary hack includes method till base and chrome use new name. + void Decrement(int value) { + Add(-value); + } + + // Is this counter enabled? + // Returns false if table is full. + bool Enabled() { + return GetPtr() != NULL; + } + + int value() { + int* loc = GetPtr(); + if (loc) return *loc; + return 0; + } + + protected: + StatsCounter() + : counter_id_(-1) { + } + + // Returns the cached address of this counter location. + int* GetPtr() { + StatsTable* table = StatsTable::current(); + if (!table) + return NULL; + + // If counter_id_ is -1, then we haven't looked it up yet. + if (counter_id_ == -1) { + counter_id_ = table->FindCounter(name_); + if (table->GetSlot() == 0) { + if (!table->RegisterThread(L"")) { + // There is no room for this thread. This thread + // cannot use counters. + counter_id_ = 0; + return NULL; + } + } + } + + // If counter_id_ is > 0, then we have a valid counter. + if (counter_id_ > 0) + return table->GetLocation(counter_id_, table->GetSlot()); + + // counter_id_ was zero, which means the table is full. + return NULL; + } + + std::wstring name_; + // The counter id in the table. We initialize to -1 (an invalid value) + // and then cache it once it has been looked up. The counter_id is + // valid across all threads and processes. + int32 counter_id_; +}; + + +// A StatsCounterTimer is a StatsCounter which keeps a timer during +// the scope of the StatsCounterTimer. On destruction, it will record +// its time measurement. +class StatsCounterTimer : protected StatsCounter { + public: + // Constructs and starts the timer. + explicit StatsCounterTimer(const std::wstring& name) { + // we prepend the name with 't:' to indicate that it is a timer. + name_ = L"t:"; + name_.append(name); + } + + // Start the timer. + void Start() { + if (!Enabled()) + return; + start_time_ = TimeTicks::Now(); + stop_time_ = TimeTicks(); + } + + // Stop the timer and record the results. + void Stop() { + if (!Enabled() || !Running()) + return; + stop_time_ = TimeTicks::Now(); + Record(); + } + + // Returns true if the timer is running. + bool Running() { + return Enabled() && !start_time_.is_null() && stop_time_.is_null(); + } + + // Accept a TimeDelta to increment. + virtual void AddTime(TimeDelta time) { + Add(static_cast<int>(time.InMilliseconds())); + } + + // TODO(jar) temporary hack include method till base and chrome use new name. + void IncrementTimer(TimeDelta time) { + AddTime(time); + } + + protected: + // Compute the delta between start and stop, in milliseconds. + void Record() { + AddTime(stop_time_ - start_time_); + } + + TimeTicks start_time_; + TimeTicks stop_time_; +}; + +// A StatsRate is a timer that keeps a count of the number of intervals added so +// that several statistics can be produced: +// min, max, avg, count, total +class StatsRate : public StatsCounterTimer { + public: + // Constructs and starts the timer. + explicit StatsRate(const wchar_t* name) + : StatsCounterTimer(name), + counter_(name), + largest_add_(std::wstring(L" ").append(name).append(L"MAX").c_str()) { + } + + virtual void Add(int value) { + counter_.Increment(); + StatsCounterTimer::Add(value); + if (value > largest_add_.value()) + largest_add_.Set(value); + } + + private: + StatsCounter counter_; + StatsCounter largest_add_; +}; + + +// Helper class for scoping a timer or rate. +template<class T> class StatsScope { + public: + explicit StatsScope<T>(T& timer) + : timer_(timer) { + timer_.Start(); + } + + ~StatsScope() { + timer_.Stop(); + } + + void Stop() { + timer_.Stop(); + } + + private: + T& timer_; +}; + +#endif // BASE_STATS_COUNTERS_H__ |