13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved.
23345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Use of this source code is governed by a BSD-style license that can be
33345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// found in the LICENSE file.
43345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/stats_counters.h"
6731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
7731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace base {
83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
93345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickStatsCounter::StatsCounter(const std::string& name)
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : counter_id_(-1) {
113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We prepend the name with 'c:' to indicate that it is a counter.
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (StatsTable::current()) {
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // TODO(mbelshe): name_ construction is racy and it may corrupt memory for
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // static.
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    name_ = "c:";
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    name_.append(name);
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
203345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickStatsCounter::~StatsCounter() {
213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid StatsCounter::Set(int value) {
243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int* loc = GetPtr();
253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (loc)
263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    *loc = value;
273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid StatsCounter::Add(int value) {
303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int* loc = GetPtr();
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (loc)
323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    (*loc) += value;
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
353345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickStatsCounter::StatsCounter()
363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : counter_id_(-1) {
373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint* StatsCounter::GetPtr() {
403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  StatsTable* table = StatsTable::current();
413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!table)
423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return NULL;
433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // If counter_id_ is -1, then we haven't looked it up yet.
453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (counter_id_ == -1) {
463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    counter_id_ = table->FindCounter(name_);
473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (table->GetSlot() == 0) {
483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (!table->RegisterThread("")) {
493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        // There is no room for this thread.  This thread
503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        // cannot use counters.
513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        counter_id_ = 0;
523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        return NULL;
533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // If counter_id_ is > 0, then we have a valid counter.
583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (counter_id_ > 0)
593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return table->GetLocation(counter_id_, table->GetSlot());
603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // counter_id_ was zero, which means the table is full.
623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return NULL;
633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
663345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickStatsCounterTimer::StatsCounterTimer(const std::string& name) {
673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // we prepend the name with 't:' to indicate that it is a timer.
68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (StatsTable::current()) {
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // TODO(mbelshe): name_ construction is racy and it may corrupt memory for
70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // static.
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    name_ = "t:";
72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    name_.append(name);
73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
763345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickStatsCounterTimer::~StatsCounterTimer() {
773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid StatsCounterTimer::Start() {
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!Enabled())
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return;
82731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  start_time_ = TimeTicks::Now();
83731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  stop_time_ = TimeTicks();
843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Stop the timer and record the results.
873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid StatsCounterTimer::Stop() {
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!Enabled() || !Running())
893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return;
90731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  stop_time_ = TimeTicks::Now();
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Record();
923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Returns true if the timer is running.
953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool StatsCounterTimer::Running() {
963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return Enabled() && !start_time_.is_null() && stop_time_.is_null();
973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Accept a TimeDelta to increment.
100731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid StatsCounterTimer::AddTime(TimeDelta time) {
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Add(static_cast<int>(time.InMilliseconds()));
1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid StatsCounterTimer::Record() {
1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  AddTime(stop_time_ - start_time_);
1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
109731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickStatsRate::StatsRate(const std::string& name)
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : StatsCounterTimer(name),
1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      counter_(name),
112731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      largest_add_(std::string(" ").append(name).append("MAX")) {
1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickStatsRate::~StatsRate() {
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid StatsRate::Add(int value) {
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  counter_.Increment();
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  StatsCounterTimer::Add(value);
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (value > largest_add_.value())
1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    largest_add_.Set(value);
1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
124731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}  // namespace base
126