summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-06 00:09:37 +0000
committerjar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-06 00:09:37 +0000
commite8829a1981a2d9d849c377c28f9444fdefee0f44 (patch)
tree3cfe522cf76d308dec9fca773d3f9495e12abc5e
parent4f3b65a30cad88c1f1e482f7bda69ef50f8e1364 (diff)
downloadchromium_src-e8829a1981a2d9d849c377c28f9444fdefee0f44.zip
chromium_src-e8829a1981a2d9d849c377c28f9444fdefee0f44.tar.gz
chromium_src-e8829a1981a2d9d849c377c28f9444fdefee0f44.tar.bz2
Use factory to create histograms, and refcounts to track lifetimes
This is CL patch 377028 by Raman Tenneti, with minor changes to make the try-bots happier. It is cleanup that better ensures lifetimes of histograms (making it harder for users to abuse them). bug=16495 (repairs leak induced by the first landing) bug=18840 (should make leaks less possible) tbr=raman.tenneti Review URL: http://codereview.chromium.org/462027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33933 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/histogram.cc262
-rw-r--r--base/histogram.h317
-rw-r--r--base/histogram_unittest.cc129
-rw-r--r--base/message_loop.cc7
-rw-r--r--base/message_loop.h2
-rw-r--r--chrome/browser/chrome_browser_application_mac.mm9
-rw-r--r--chrome/browser/diagnostics/sqlite_diagnostics.cc8
-rw-r--r--chrome/browser/jankometer.cc22
-rw-r--r--chrome/browser/net/dns_host_info.cc9
-rw-r--r--chrome/browser/net/websocket_experiment/websocket_experiment_runner.cc72
-rw-r--r--chrome/browser/renderer_host/buffered_resource_handler.cc25
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_blocking_page.cc8
-rw-r--r--chrome/browser/ssl/ssl_blocking_page.cc8
-rw-r--r--chrome/browser/sync/profile_sync_service.cc11
-rw-r--r--chrome/renderer/render_thread.cc16
-rw-r--r--net/base/connection_type_histograms.cc22
-rw-r--r--net/base/mime_sniffer.cc86
-rw-r--r--net/base/sdch_manager.cc9
-rw-r--r--net/disk_cache/histogram_macros.h8
-rw-r--r--net/disk_cache/stats.cc3
-rw-r--r--net/disk_cache/stats.h2
-rw-r--r--net/disk_cache/stats_histogram.cc31
-rw-r--r--net/disk_cache/stats_histogram.h16
-rw-r--r--net/ftp/ftp_network_transaction.cc22
-rw-r--r--net/ftp/ftp_server_type_histograms.cc22
-rw-r--r--net/http/http_network_transaction.cc49
-rw-r--r--net/socket_stream/socket_stream_metrics.cc22
27 files changed, 774 insertions, 423 deletions
diff --git a/base/histogram.cc b/base/histogram.cc
index 55af96d..3a5a5b2 100644
--- a/base/histogram.cc
+++ b/base/histogram.cc
@@ -23,7 +23,42 @@ typedef Histogram::Count Count;
// static
const int Histogram::kHexRangePrintingFlag = 0x8000;
-Histogram::Histogram(const char* name, Sample minimum,
+scoped_refptr<Histogram> Histogram::HistogramFactoryGet(
+ const std::string& name, Sample minimum, Sample maximum,
+ size_t bucket_count) {
+ scoped_refptr<Histogram> histogram(NULL);
+
+ // Defensive code.
+ if (minimum <= 0)
+ minimum = 1;
+ if (maximum >= kSampleType_MAX)
+ maximum = kSampleType_MAX - 1;
+
+ if (StatisticsRecorder::FindHistogram(name, &histogram)) {
+ DCHECK(histogram.get() != NULL);
+ } else {
+ histogram = new Histogram(name, minimum, maximum, bucket_count);
+ scoped_refptr<Histogram> registered_histogram(NULL);
+ StatisticsRecorder::FindHistogram(name, &registered_histogram);
+ // Allow a NULL return to mean that the StatisticsRecorder was not started.
+ if (registered_histogram.get() != NULL &&
+ registered_histogram.get() != histogram.get())
+ histogram = registered_histogram;
+ }
+
+ DCHECK(HISTOGRAM == histogram->histogram_type());
+ DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count));
+ return histogram;
+}
+
+scoped_refptr<Histogram> Histogram::HistogramFactoryGet(
+ const std::string& name, base::TimeDelta minimum, base::TimeDelta maximum,
+ size_t bucket_count) {
+ return HistogramFactoryGet(name,
+ minimum.InMilliseconds(), maximum.InMilliseconds(), bucket_count);
+}
+
+Histogram::Histogram(const std::string& name, Sample minimum,
Sample maximum, size_t bucket_count)
: histogram_name_(name),
declared_min_(minimum),
@@ -31,12 +66,11 @@ Histogram::Histogram(const char* name, Sample minimum,
bucket_count_(bucket_count),
flags_(0),
ranges_(bucket_count + 1, 0),
- sample_(),
- registered_(false) {
+ sample_() {
Initialize();
}
-Histogram::Histogram(const char* name, TimeDelta minimum,
+Histogram::Histogram(const std::string& name, TimeDelta minimum,
TimeDelta maximum, size_t bucket_count)
: histogram_name_(name),
declared_min_(static_cast<int> (minimum.InMilliseconds())),
@@ -44,21 +78,23 @@ Histogram::Histogram(const char* name, TimeDelta minimum,
bucket_count_(bucket_count),
flags_(0),
ranges_(bucket_count + 1, 0),
- sample_(),
- registered_(false) {
+ sample_() {
Initialize();
}
Histogram::~Histogram() {
- if (registered_)
- StatisticsRecorder::UnRegister(this);
+ DCHECK(!(kPlannedLeakFlag & flags_));
+ if (StatisticsRecorder::dump_on_exit()) {
+ std::string output;
+ WriteAscii(true, "\n", &output);
+ LOG(INFO) << output;
+ }
+
// Just to make sure most derived class did this properly...
DCHECK(ValidateBucketRanges());
}
void Histogram::Add(int value) {
- if (!registered_)
- registered_ = StatisticsRecorder::Register(this);
if (value >= kSampleType_MAX)
value = kSampleType_MAX - 1;
if (value < 0)
@@ -170,7 +206,7 @@ void Histogram::Initialize() {
ranges_[bucket_count_] = kSampleType_MAX;
InitializeBucketRange();
DCHECK(ValidateBucketRanges());
- registered_ = StatisticsRecorder::Register(this);
+ StatisticsRecorder::Register(this);
}
// Calculate what range of values are held in each bucket.
@@ -353,14 +389,15 @@ void Histogram::WriteAsciiBucketGraph(double current_size, double max_size,
// static
std::string Histogram::SerializeHistogramInfo(const Histogram& histogram,
const SampleSet& snapshot) {
- Pickle pickle;
+ DCHECK(histogram.histogram_type() != NOT_VALID_IN_RENDERER);
+ Pickle pickle;
pickle.WriteString(histogram.histogram_name());
pickle.WriteInt(histogram.declared_min());
pickle.WriteInt(histogram.declared_max());
pickle.WriteSize(histogram.bucket_count());
pickle.WriteInt(histogram.histogram_type());
- pickle.WriteInt(histogram.flags());
+ pickle.WriteInt(histogram.flags() & ~kIPCSerializationSourceFlag);
snapshot.Serialize(&pickle);
return std::string(static_cast<const char*>(pickle.data()), pickle.size());
@@ -394,27 +431,27 @@ bool Histogram::DeserializeHistogramInfo(const std::string& histogram_info) {
return false;
}
- Histogram* render_histogram =
- StatisticsRecorder::GetHistogram(histogram_name);
-
- if (render_histogram == NULL) {
- if (histogram_type == EXPONENTIAL) {
- render_histogram = new Histogram(histogram_name.c_str(),
- declared_min,
- declared_max,
- bucket_count);
- } else if (histogram_type == LINEAR) {
- render_histogram = new LinearHistogram(histogram_name.c_str(),
- declared_min,
- declared_max,
- bucket_count);
- } else {
- LOG(ERROR) << "Error Deserializing Histogram Unknown histogram_type: " <<
- histogram_type;
- return false;
- }
- DCHECK(!(flags & kRendererHistogramFlag));
- render_histogram->SetFlags(flags | kRendererHistogramFlag);
+ DCHECK(histogram_type != NOT_VALID_IN_RENDERER);
+
+ scoped_refptr<Histogram> render_histogram(NULL);
+
+ if (histogram_type == HISTOGRAM) {
+ render_histogram = Histogram::HistogramFactoryGet(
+ histogram_name, declared_min, declared_max, bucket_count);
+ } else if (histogram_type == LINEAR_HISTOGRAM) {
+ render_histogram = LinearHistogram::LinearHistogramFactoryGet(
+ histogram_name, declared_min, declared_max, bucket_count);
+ } else if (histogram_type == BOOLEAN_HISTOGRAM) {
+ render_histogram = BooleanHistogram::BooleanHistogramFactoryGet(
+ histogram_name);
+ } else if (histogram_type == THREAD_SAFE_HISTOGRAM) {
+ render_histogram =
+ ThreadSafeHistogram::ThreadSafeHistogramFactoryGet(
+ histogram_name, declared_min, declared_max, bucket_count);
+ } else {
+ LOG(ERROR) << "Error Deserializing Histogram Unknown histogram_type: " <<
+ histogram_type;
+ return false;
}
DCHECK(declared_min == render_histogram->declared_min());
@@ -422,17 +459,16 @@ bool Histogram::DeserializeHistogramInfo(const std::string& histogram_info) {
DCHECK(bucket_count == render_histogram->bucket_count());
DCHECK(histogram_type == render_histogram->histogram_type());
- if (render_histogram->flags() & kRendererHistogramFlag) {
- render_histogram->AddSampleSet(sample);
- } else {
- DLOG(INFO) << "Single thread mode, histogram observed and not copied: " <<
+ if (render_histogram->flags() & kIPCSerializationSourceFlag) {
+ DLOG(INFO) << "Single process mode, histogram observed and not copied: " <<
histogram_name;
+ } else {
+ render_histogram->AddSampleSet(sample);
}
return true;
}
-
//------------------------------------------------------------------------------
// Methods for the Histogram::SampleSet class
//------------------------------------------------------------------------------
@@ -537,14 +573,48 @@ bool Histogram::SampleSet::Deserialize(void** iter, const Pickle& pickle) {
// buckets.
//------------------------------------------------------------------------------
-LinearHistogram::LinearHistogram(const char* name, Sample minimum,
+scoped_refptr<Histogram> LinearHistogram::LinearHistogramFactoryGet(
+ const std::string& name, Sample minimum, Sample maximum,
+ size_t bucket_count) {
+ scoped_refptr<Histogram> histogram(NULL);
+
+ if (minimum <= 0)
+ minimum = 1;
+ if (maximum >= kSampleType_MAX)
+ maximum = kSampleType_MAX - 1;
+
+ if (StatisticsRecorder::FindHistogram(name, &histogram)) {
+ DCHECK(histogram.get() != NULL);
+ } else {
+ histogram = new LinearHistogram(name, minimum, maximum, bucket_count);
+ scoped_refptr<Histogram> registered_histogram(NULL);
+ StatisticsRecorder::FindHistogram(name, &registered_histogram);
+ if (registered_histogram.get() != NULL &&
+ registered_histogram.get() != histogram.get())
+ histogram = registered_histogram;
+ }
+
+ DCHECK(LINEAR_HISTOGRAM == histogram->histogram_type());
+ DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count));
+
+ return histogram;
+}
+
+scoped_refptr<Histogram> LinearHistogram::LinearHistogramFactoryGet(
+ const std::string& name, base::TimeDelta minimum, base::TimeDelta maximum,
+ size_t bucket_count) {
+ return LinearHistogramFactoryGet(name, minimum.InMilliseconds(),
+ maximum.InMilliseconds(), bucket_count);
+}
+
+LinearHistogram::LinearHistogram(const std::string& name, Sample minimum,
Sample maximum, size_t bucket_count)
: Histogram(name, minimum >= 1 ? minimum : 1, maximum, bucket_count) {
InitializeBucketRange();
DCHECK(ValidateBucketRanges());
}
-LinearHistogram::LinearHistogram(const char* name,
+LinearHistogram::LinearHistogram(const std::string& name,
TimeDelta minimum, TimeDelta maximum, size_t bucket_count)
: Histogram(name, minimum >= TimeDelta::FromMilliseconds(1) ?
minimum : TimeDelta::FromMilliseconds(1),
@@ -595,11 +665,61 @@ double LinearHistogram::GetBucketSize(Count current, size_t i) const {
}
//------------------------------------------------------------------------------
+// This section provides implementation for BooleanHistogram.
+//------------------------------------------------------------------------------
+
+scoped_refptr<Histogram> BooleanHistogram::BooleanHistogramFactoryGet(
+ const std::string& name) {
+ scoped_refptr<Histogram> histogram(NULL);
+
+ if (StatisticsRecorder::FindHistogram(name, &histogram)) {
+ DCHECK(histogram.get() != NULL);
+ } else {
+ histogram = new BooleanHistogram(name);
+ scoped_refptr<Histogram> registered_histogram(NULL);
+ StatisticsRecorder::FindHistogram(name, &registered_histogram);
+ if (registered_histogram.get() != NULL &&
+ registered_histogram.get() != histogram.get())
+ histogram = registered_histogram;
+ }
+
+ DCHECK(BOOLEAN_HISTOGRAM == histogram->histogram_type());
+
+ return histogram;
+}
+
+//------------------------------------------------------------------------------
// This section provides implementation for ThreadSafeHistogram.
//------------------------------------------------------------------------------
-ThreadSafeHistogram::ThreadSafeHistogram(const char* name, Sample minimum,
- Sample maximum, size_t bucket_count)
+scoped_refptr<Histogram> ThreadSafeHistogram::ThreadSafeHistogramFactoryGet(
+ const std::string& name, Sample minimum, Sample maximum,
+ size_t bucket_count) {
+ scoped_refptr<Histogram> histogram(NULL);
+
+ if (minimum <= 0)
+ minimum = 1;
+ if (maximum >= kSampleType_MAX)
+ maximum = kSampleType_MAX - 1;
+
+ if (StatisticsRecorder::FindHistogram(name, &histogram)) {
+ DCHECK(histogram.get() != NULL);
+ } else {
+ histogram = new ThreadSafeHistogram(name, minimum, maximum, bucket_count);
+ scoped_refptr<Histogram> registered_histogram(NULL);
+ StatisticsRecorder::FindHistogram(name, &registered_histogram);
+ if (registered_histogram.get() != NULL &&
+ registered_histogram.get() != histogram.get())
+ histogram = registered_histogram;
+ }
+
+ DCHECK(THREAD_SAFE_HISTOGRAM == histogram->histogram_type());
+ DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count));
+ return histogram;
+}
+
+ThreadSafeHistogram::ThreadSafeHistogram(const std::string& name,
+ Sample minimum, Sample maximum, size_t bucket_count)
: Histogram(name, minimum, maximum, bucket_count),
lock_() {
}
@@ -657,34 +777,22 @@ bool StatisticsRecorder::WasStarted() {
return NULL != histograms_;
}
+// Note: We can't accept a ref_ptr to |histogram| because we *might* not keep a
+// reference, and we are called while in the Histogram constructor. In that
+// scenario, a ref_ptr would have incremented the ref count when the histogram
+// was passed to us, decremented it when we returned, and the instance would be
+// destroyed before assignment (when value was returned by new).
// static
-bool StatisticsRecorder::Register(Histogram* histogram) {
+void StatisticsRecorder::Register(Histogram* histogram) {
if (!histograms_)
- return false;
+ return;
const std::string name = histogram->histogram_name();
AutoLock auto_lock(*lock_);
- if (histograms_->end() != histograms_->find(name)) {
- // Check to be sure it is compatible.... and if not, then do a CHECK()
- return false; // This name is already registered.
- }
- (*histograms_)[name] = histogram;
- return true;
-}
+ DCHECK(histograms_->end() == histograms_->find(name));
-// static
-void StatisticsRecorder::UnRegister(Histogram* histogram) {
- if (!histograms_)
- return;
- const std::string name = histogram->histogram_name();
- AutoLock auto_lock(*lock_);
- DCHECK(histograms_->end() != histograms_->find(name));
- histograms_->erase(name);
- if (dump_on_exit_) {
- std::string output;
- histogram->WriteAscii(true, "\n", &output);
- LOG(INFO) << output;
- }
+ (*histograms_)[name] = histogram;
+ return;
}
// static
@@ -743,17 +851,31 @@ void StatisticsRecorder::GetHistograms(Histograms* output) {
}
}
-Histogram* StatisticsRecorder::GetHistogram(const std::string& query) {
+// static
+void StatisticsRecorder::GetHistogramsForRenderer(Histograms* output) {
if (!histograms_)
- return NULL;
+ return;
AutoLock auto_lock(*lock_);
for (HistogramMap::iterator it = histograms_->begin();
histograms_->end() != it;
++it) {
- if (it->first.find(query) != std::string::npos)
- return it->second;
+ scoped_refptr<Histogram> histogram = it->second;
+ if (!(histogram->flags() & kIPCSerializationSourceFlag))
+ histogram->SetFlags(kIPCSerializationSourceFlag);
+ output->push_back(histogram);
}
- return NULL;
+}
+
+bool StatisticsRecorder::FindHistogram(const std::string& name,
+ scoped_refptr<Histogram>* histogram) {
+ if (!histograms_)
+ return false;
+ AutoLock auto_lock(*lock_);
+ HistogramMap::iterator it = histograms_->find(name);
+ if (histograms_->end() == it)
+ return false;
+ *histogram = it->second;
+ return true;
}
// private static
diff --git a/base/histogram.h b/base/histogram.h
index 4d40c1b..0c94fc0 100644
--- a/base/histogram.h
+++ b/base/histogram.h
@@ -36,6 +36,8 @@
#include <vector>
#include "base/lock.h"
+#include "base/ref_counted.h"
+#include "base/logging.h"
#include "base/time.h"
//------------------------------------------------------------------------------
@@ -43,47 +45,56 @@
// The first four macros use 50 buckets.
#define HISTOGRAM_TIMES(name, sample) do { \
- static Histogram counter((name), base::TimeDelta::FromMilliseconds(1), \
- base::TimeDelta::FromSeconds(10), 50); \
- counter.AddTime(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), base::TimeDelta::FromMilliseconds(1), \
+ base::TimeDelta::FromSeconds(10), 50); \
+ counter->AddTime(sample); \
} while (0)
#define HISTOGRAM_COUNTS(name, sample) do { \
- static Histogram counter((name), 1, 1000000, 50); \
- counter.Add(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), 1, 1000000, 50); \
+ counter->Add(sample); \
} while (0)
#define HISTOGRAM_COUNTS_100(name, sample) do { \
- static Histogram counter((name), 1, 100, 50); \
- counter.Add(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), 1, 100, 50); \
+ counter->Add(sample); \
} while (0)
#define HISTOGRAM_COUNTS_10000(name, sample) do { \
- static Histogram counter((name), 1, 10000, 50); \
- counter.Add(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), 1, 10000, 50); \
+ counter->Add(sample); \
} while (0)
#define HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \
- static Histogram counter((name), min, max, bucket_count); \
- counter.Add(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), min, max, bucket_count); \
+ counter->Add(sample); \
} while (0)
#define HISTOGRAM_PERCENTAGE(name, under_one_hundred) do { \
- static LinearHistogram counter((name), 1, 100, 101); \
- counter.Add(under_one_hundred); \
+ static scoped_refptr<Histogram> counter = \
+ LinearHistogram::LinearHistogramFactoryGet(\
+ (name), 1, 100, 101); \
+ counter->Add(under_one_hundred); \
} while (0)
// For folks that need real specific times, use this to select a precise range
// of times you want plotted, and the number of buckets you want used.
#define HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \
- static Histogram counter((name), min, max, bucket_count); \
- counter.AddTime(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), min, max, bucket_count); \
+ counter->AddTime(sample); \
} while (0)
// DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES.
#define HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \
- static Histogram counter((name), min, max, bucket_count); \
- if ((sample) < (max)) counter.AddTime(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), min, max, bucket_count); \
+ if ((sample) < (max)) counter->AddTime(sample); \
} while (0)
//------------------------------------------------------------------------------
@@ -101,12 +112,14 @@
// be equal in number or fewer than the corresponding calls to Add().
#define ASSET_HISTOGRAM_COUNTS(name, sample) do { \
- static ThreadSafeHistogram counter((name), 1, 1000000, 50); \
+ static scoped_refptr<Histogram> counter = \
+ ThreadSafeHistogram::ThreadSafeHistogramFactoryGet(\
+ (name), 1, 1000000, 50); \
if (0 == sample) break; \
if (sample >= 0) \
- counter.Add(sample); \
+ counter->Add(sample); \
else\
- counter.Remove(-sample); \
+ counter->Remove(-sample); \
} while (0)
//------------------------------------------------------------------------------
@@ -150,92 +163,122 @@
static const int kUmaTargetedHistogramFlag = 0x1;
-// This indicates the histogram is shadow copy of renderer histrogram
-// constructed by unpick method and updated regularly from renderer upload
-// of histograms.
-static const int kRendererHistogramFlag = 1 << 4;
+// This indicates the histogram is pickled to be sent across an IPC Channel.
+// If we observe this flag during unpickle method, then we are running in a
+// single process mode.
+static const int kIPCSerializationSourceFlag = 1 << 4;
+
+// Some histograms aren't currently destroyed. Until such users properly
+// decref those histograms, we will mark there histograms as planned to leak so
+// that we can catch any user that directly tries to call delete "directly"
+// rather than using the reference counting features that should take care of
+// this.
+// TODO(jar): Make this flag unnecessary!
+static const int kPlannedLeakFlag = 1 << 5;
#define UMA_HISTOGRAM_TIMES(name, sample) do { \
- static Histogram counter((name), base::TimeDelta::FromMilliseconds(1), \
- base::TimeDelta::FromSeconds(10), 50); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.AddTime(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), base::TimeDelta::FromMilliseconds(1), \
+ base::TimeDelta::FromSeconds(10), 50); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->AddTime(sample); \
} while (0)
#define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) do { \
- static Histogram counter((name), base::TimeDelta::FromMilliseconds(10), \
- base::TimeDelta::FromMinutes(3), 50); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.AddTime(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), base::TimeDelta::FromMilliseconds(10), \
+ base::TimeDelta::FromMinutes(3), 50); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->AddTime(sample); \
} while (0)
// Use this macro when times can routinely be much longer than 10 seconds.
#define UMA_HISTOGRAM_LONG_TIMES(name, sample) do { \
- static Histogram counter((name), base::TimeDelta::FromMilliseconds(1), \
- base::TimeDelta::FromHours(1), 50); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.AddTime(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), base::TimeDelta::FromMilliseconds(1), \
+ base::TimeDelta::FromHours(1), 50); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->AddTime(sample); \
} while (0)
#define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \
- static Histogram counter((name), min, max, bucket_count); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.AddTime(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), min, max, bucket_count); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->AddTime(sample); \
} while (0)
#define UMA_HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \
- static Histogram counter((name), min, max, bucket_count); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- if ((sample) < (max)) counter.AddTime(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), min, max, bucket_count); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ if ((sample) < (max)) counter->AddTime(sample); \
} while (0)
#define UMA_HISTOGRAM_COUNTS(name, sample) do { \
- static Histogram counter((name), 1, 1000000, 50); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.Add(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), 1, 1000000, 50); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->Add(sample); \
} while (0)
#define UMA_HISTOGRAM_COUNTS_100(name, sample) do { \
- static Histogram counter((name), 1, 100, 50); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.Add(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), 1, 100, 50); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->Add(sample); \
} while (0)
#define UMA_HISTOGRAM_COUNTS_10000(name, sample) do { \
- static Histogram counter((name), 1, 10000, 50); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.Add(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), 1, 10000, 50); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->Add(sample); \
} while (0)
#define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \
- static Histogram counter((name), min, max, bucket_count); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.Add(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), min, max, bucket_count); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->Add(sample); \
} while (0)
#define UMA_HISTOGRAM_MEMORY_KB(name, sample) do { \
- static Histogram counter((name), 1000, 500000, 50); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.Add(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), 1000, 500000, 50); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->Add(sample); \
} while (0)
#define UMA_HISTOGRAM_MEMORY_MB(name, sample) do { \
- static Histogram counter((name), 1, 1000, 50); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.Add(sample); \
+ static scoped_refptr<Histogram> counter = Histogram::HistogramFactoryGet(\
+ (name), 1, 1000, 50); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->Add(sample); \
} while (0)
#define UMA_HISTOGRAM_PERCENTAGE(name, under_one_hundred) do { \
- static LinearHistogram counter((name), 1, 100, 101); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.Add(under_one_hundred); \
+ static scoped_refptr<Histogram> counter = \
+ LinearHistogram::LinearHistogramFactoryGet(\
+ (name), 1, 100, 101); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->Add(under_one_hundred); \
} while (0)
//------------------------------------------------------------------------------
class Pickle;
+class Histogram;
+class LinearHistogram;
+class BooleanHistogram;
+class ThreadSafeHistogram;
+
+namespace disk_cache {
+ class StatsHistogram;
+}; // namespace disk_cache
-class Histogram {
+
+class Histogram : public base::RefCountedThreadSafe<Histogram> {
public:
typedef int Sample; // Used for samples (and ranges of samples).
typedef int Count; // Used to count samples in a bucket.
@@ -246,11 +289,26 @@ class Histogram {
static const int kHexRangePrintingFlag;
+ /* These enums are meant to facilitate deserialization of renderer histograms
+ into the browser. */
+ enum ClassType {
+ HISTOGRAM,
+ LINEAR_HISTOGRAM,
+ BOOLEAN_HISTOGRAM,
+ THREAD_SAFE_HISTOGRAM,
+ NOT_VALID_IN_RENDERER
+ };
+
enum BucketLayout {
EXPONENTIAL,
LINEAR
};
+ struct DescriptionPair {
+ Sample sample;
+ const char* description; // Null means end of a list of pairs.
+ };
+
//----------------------------------------------------------------------------
// Statistic values, developed over the life of the histogram.
@@ -288,14 +346,18 @@ class Histogram {
int64 square_sum_; // sum of squares of samples.
};
//----------------------------------------------------------------------------
-
- Histogram(const char* name, Sample minimum,
- Sample maximum, size_t bucket_count);
- Histogram(const char* name, base::TimeDelta minimum,
- base::TimeDelta maximum, size_t bucket_count);
- virtual ~Histogram();
+ // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit
+ // default underflow bucket.
+ static scoped_refptr<Histogram> HistogramFactoryGet(const std::string& name,
+ Sample minimum, Sample maximum, size_t bucket_count);
+ static scoped_refptr<Histogram> HistogramFactoryGet(const std::string& name,
+ base::TimeDelta minimum, base::TimeDelta maximum, size_t bucket_count);
void Add(int value);
+
+ // This method is an interface, used only by BooleanHistogram.
+ virtual void AddBoolean(bool value) { DCHECK(false); }
+
// Accept a TimeDelta to increment.
void AddTime(base::TimeDelta time) {
Add(static_cast<int>(time.InMilliseconds()));
@@ -303,6 +365,13 @@ class Histogram {
void AddSampleSet(const SampleSet& sample);
+ // This method is an interface, used only by ThreadSafeHistogram.
+ virtual void Remove(int value) { DCHECK(false); }
+
+ // This method is an interface, used only by LinearHistogram.
+ virtual void SetRangeDescriptions(const DescriptionPair descriptions[])
+ { DCHECK(false); }
+
// The following methods provide graphical histogram displays.
void WriteHTMLGraph(std::string* output) const;
void WriteAscii(bool graph_it, const std::string& newline,
@@ -315,8 +384,6 @@ class Histogram {
void ClearFlags(int flags) { flags_ &= ~flags; }
int flags() const { return flags_; }
- virtual BucketLayout histogram_type() const { return EXPONENTIAL; }
-
// Convenience methods for serializing/deserializing the histograms.
// Histograms from Renderer process are serialized and sent to the browser.
// Browser process reconstructs the histogram from the pickled version
@@ -332,10 +399,10 @@ class Histogram {
// browser process.
static bool DeserializeHistogramInfo(const std::string& histogram_info);
-
//----------------------------------------------------------------------------
- // Accessors for serialization and testing.
+ // Accessors for factory constuction, serialization and testing.
//----------------------------------------------------------------------------
+ virtual ClassType histogram_type() const { return HISTOGRAM; }
const std::string histogram_name() const { return histogram_name_; }
Sample declared_min() const { return declared_min_; }
Sample declared_max() const { return declared_max_; }
@@ -345,7 +412,28 @@ class Histogram {
// Override with atomic/locked snapshot if needed.
virtual void SnapshotSample(SampleSet* sample) const;
+ virtual bool HasConstructorArguments(Sample minimum, Sample maximum,
+ size_t bucket_count) {
+ return ((minimum == declared_min_) && (maximum == declared_max_) &&
+ (bucket_count == bucket_count_));
+ }
+
+ virtual bool HasConstructorTimeDeltaArguments(base::TimeDelta minimum,
+ base::TimeDelta maximum, size_t bucket_count) {
+ return ((minimum.InMilliseconds() == declared_min_) &&
+ (maximum.InMilliseconds() == declared_max_) &&
+ (bucket_count == bucket_count_));
+ }
+
protected:
+ friend class base::RefCountedThreadSafe<Histogram>;
+ Histogram(const std::string& name, Sample minimum,
+ Sample maximum, size_t bucket_count);
+ Histogram(const std::string& name, base::TimeDelta minimum,
+ base::TimeDelta maximum, size_t bucket_count);
+
+ virtual ~Histogram();
+
// Method to override to skip the display of the i'th bucket if it's empty.
virtual bool PrintEmptyBucket(size_t index) const { return true; }
@@ -434,9 +522,6 @@ class Histogram {
// sample.
SampleSet sample_;
- // Indicate if successfully registered.
- bool registered_;
-
DISALLOW_COPY_AND_ASSIGN(Histogram);
};
@@ -446,24 +531,30 @@ class Histogram {
// buckets.
class LinearHistogram : public Histogram {
public:
- struct DescriptionPair {
- Sample sample;
- const char* description; // Null means end of a list of pairs.
- };
- LinearHistogram(const char* name, Sample minimum,
- Sample maximum, size_t bucket_count);
-
- LinearHistogram(const char* name, base::TimeDelta minimum,
- base::TimeDelta maximum, size_t bucket_count);
- ~LinearHistogram() {}
+ virtual ClassType histogram_type() const { return LINEAR_HISTOGRAM; }
// Store a list of number/text values for use in rendering the histogram.
// The last element in the array has a null in its "description" slot.
- void SetRangeDescriptions(const DescriptionPair descriptions[]);
+ virtual void SetRangeDescriptions(const DescriptionPair descriptions[]);
- virtual BucketLayout histogram_type() const { return LINEAR; }
+ /* minimum should start from 1. 0 is as minimum is invalid. 0 is an implicit
+ default underflow bucket. */
+ static scoped_refptr<Histogram> LinearHistogramFactoryGet(
+ const std::string& name, Sample minimum, Sample maximum,
+ size_t bucket_count);
+ static scoped_refptr<Histogram> LinearHistogramFactoryGet(
+ const std::string& name, base::TimeDelta minimum,
+ base::TimeDelta maximum, size_t bucket_count);
protected:
+ LinearHistogram(const std::string& name, Sample minimum,
+ Sample maximum, size_t bucket_count);
+
+ LinearHistogram(const std::string& name, base::TimeDelta minimum,
+ base::TimeDelta maximum, size_t bucket_count);
+
+ virtual ~LinearHistogram() {}
+
// Initialize ranges_ mapping.
virtual void InitializeBucketRange();
virtual double GetBucketSize(Count current, size_t i) const;
@@ -491,13 +582,18 @@ class LinearHistogram : public Histogram {
// BooleanHistogram is a histogram for booleans.
class BooleanHistogram : public LinearHistogram {
public:
- explicit BooleanHistogram(const char* name)
- : LinearHistogram(name, 0, 2, 3) {
- }
+ static scoped_refptr<Histogram> BooleanHistogramFactoryGet(
+ const std::string& name);
+
+ virtual ClassType histogram_type() const { return BOOLEAN_HISTOGRAM; }
- void AddBoolean(bool value) { Add(value ? 1 : 0); }
+ virtual void AddBoolean(bool value) { Add(value ? 1 : 0); }
private:
+ explicit BooleanHistogram(const std::string& name)
+ : LinearHistogram(name, 1, 2, 3) {
+ }
+
DISALLOW_COPY_AND_ASSIGN(BooleanHistogram);
};
@@ -507,13 +603,21 @@ class BooleanHistogram : public LinearHistogram {
class ThreadSafeHistogram : public Histogram {
public:
- ThreadSafeHistogram(const char* name, Sample minimum,
- Sample maximum, size_t bucket_count);
+ static scoped_refptr<Histogram> ThreadSafeHistogramFactoryGet(
+ const std::string& name, Sample minimum, Sample maximum,
+ size_t bucket_count);
+
+ virtual ClassType histogram_type() const { return THREAD_SAFE_HISTOGRAM; }
// Provide the analog to Add()
- void Remove(int value);
+ virtual void Remove(int value);
protected:
+ ThreadSafeHistogram(const std::string& name, Sample minimum,
+ Sample maximum, size_t bucket_count);
+
+ virtual ~ThreadSafeHistogram() {}
+
// Provide locked versions to get precise counts.
virtual void Accumulate(Sample value, Count count, size_t index);
@@ -532,7 +636,7 @@ class ThreadSafeHistogram : public Histogram {
class StatisticsRecorder {
public:
- typedef std::vector<Histogram*> Histograms;
+ typedef std::vector<scoped_refptr<Histogram> > Histograms;
StatisticsRecorder();
@@ -542,10 +646,7 @@ class StatisticsRecorder {
static bool WasStarted();
// Register, or add a new histogram to the collection of statistics.
- // Return true if registered.
- static bool Register(Histogram* histogram);
- // Unregister, or remove, a histogram from the collection of statistics.
- static void UnRegister(Histogram* histogram);
+ static void Register(Histogram* histogram);
// Methods for printing histograms. Only histograms which have query as
// a substring are written to output (an empty string will process all
@@ -556,8 +657,16 @@ class StatisticsRecorder {
// Method for extracting histograms which were marked for use by UMA.
static void GetHistograms(Histograms* output);
- // Find a histogram by name. This method is thread safe.
- static Histogram* GetHistogram(const std::string& query);
+ // Method for extracting histograms for renderer and the histogram's flag is
+ // set to kIPCSerializationSourceFlag.
+ static void GetHistogramsForRenderer(Histograms* output);
+
+ // Find a histogram by name. It matches the exact name. This method is thread
+ // safe.
+ static bool FindHistogram(const std::string& query,
+ scoped_refptr<Histogram>* histogram);
+
+ static bool dump_on_exit() { return dump_on_exit_; }
static void set_dump_on_exit(bool enable) { dump_on_exit_ = enable; }
@@ -570,7 +679,7 @@ class StatisticsRecorder {
private:
// We keep all registered histograms in a map, from name to histogram.
- typedef std::map<std::string, Histogram*> HistogramMap;
+ typedef std::map<std::string, scoped_refptr<Histogram> > HistogramMap;
static HistogramMap* histograms_;
diff --git a/base/histogram_unittest.cc b/base/histogram_unittest.cc
index 3f2ed4c..4d5de51 100644
--- a/base/histogram_unittest.cc
+++ b/base/histogram_unittest.cc
@@ -19,11 +19,17 @@ class HistogramTest : public testing::Test {
// Check for basic syntax and use.
TEST(HistogramTest, StartupShutdownTest) {
// Try basic construction
- Histogram histogram("TestHistogram", 1, 1000, 10);
- Histogram histogram1("Test1Histogram", 1, 1000, 10);
-
- LinearHistogram linear_histogram("TestLinearHistogram", 1, 1000, 10);
- LinearHistogram linear_histogram1("Test1LinearHistogram", 1, 1000, 10);
+ scoped_refptr<Histogram> histogram =
+ Histogram::HistogramFactoryGet("TestHistogram", 1, 1000, 10);
+ scoped_refptr<Histogram> histogram1 =
+ Histogram::HistogramFactoryGet("Test1Histogram", 1, 1000, 10);
+
+ scoped_refptr<Histogram> linear_histogram =
+ LinearHistogram::LinearHistogramFactoryGet("TestLinearHistogram", 1, 1000,
+ 10);
+ scoped_refptr<Histogram> linear_histogram1 =
+ LinearHistogram::LinearHistogramFactoryGet("Test1LinearHistogram", 1,
+ 1000, 10);
// Use standard macros (but with fixed samples)
HISTOGRAM_TIMES("Test2Histogram", TimeDelta::FromDays(1));
@@ -57,17 +63,23 @@ TEST(HistogramTest, RecordedStartupTest) {
EXPECT_EQ(0U, histograms.size());
// Try basic construction
- Histogram histogram("TestHistogram", 1, 1000, 10);
+ scoped_refptr<Histogram> histogram =
+ Histogram::HistogramFactoryGet("TestHistogram", 1, 1000, 10);
histograms.clear();
StatisticsRecorder::GetHistograms(&histograms); // Load up lists
EXPECT_EQ(1U, histograms.size());
- Histogram histogram1("Test1Histogram", 1, 1000, 10);
+ scoped_refptr<Histogram> histogram1 =
+ Histogram::HistogramFactoryGet("Test1Histogram", 1, 1000, 10);
histograms.clear();
StatisticsRecorder::GetHistograms(&histograms); // Load up lists
EXPECT_EQ(2U, histograms.size());
- LinearHistogram linear_histogram("TestLinearHistogram", 1, 1000, 10);
- LinearHistogram linear_histogram1("Test1LinearHistogram", 1, 1000, 10);
+ scoped_refptr<Histogram> linear_histogram =
+ LinearHistogram::LinearHistogramFactoryGet(
+ "TestLinearHistogram", 1, 1000, 10);
+ scoped_refptr<Histogram> linear_histogram1 =
+ LinearHistogram::LinearHistogramFactoryGet(
+ "Test1LinearHistogram", 1, 1000, 10);
histograms.clear();
StatisticsRecorder::GetHistograms(&histograms); // Load up lists
EXPECT_EQ(4U, histograms.size());
@@ -102,55 +114,62 @@ TEST(HistogramTest, RangeTest) {
recorder.GetHistograms(&histograms);
EXPECT_EQ(0U, histograms.size());
- Histogram histogram("Histogram", 1, 64, 8); // As mentioned in header file.
+ scoped_refptr<Histogram> histogram = Histogram::HistogramFactoryGet(
+ "Histogram", 1, 64, 8); // As mentioned in header file.
// Check that we got a nice exponential when there was enough rooom.
- EXPECT_EQ(0, histogram.ranges(0));
+ EXPECT_EQ(0, histogram->ranges(0));
int power_of_2 = 1;
for (int i = 1; i < 8; i++) {
- EXPECT_EQ(power_of_2, histogram.ranges(i));
+ EXPECT_EQ(power_of_2, histogram->ranges(i));
power_of_2 *= 2;
}
- EXPECT_EQ(INT_MAX, histogram.ranges(8));
+ EXPECT_EQ(INT_MAX, histogram->ranges(8));
- Histogram short_histogram("Histogram Shortened", 1, 7, 8);
+ scoped_refptr<Histogram> short_histogram =
+ Histogram::HistogramFactoryGet("Histogram Shortened", 1, 7, 8);
// Check that when the number of buckets is short, we get a linear histogram
// for lack of space to do otherwise.
for (int i = 0; i < 8; i++)
- EXPECT_EQ(i, short_histogram.ranges(i));
- EXPECT_EQ(INT_MAX, short_histogram.ranges(8));
+ EXPECT_EQ(i, short_histogram->ranges(i));
+ EXPECT_EQ(INT_MAX, short_histogram->ranges(8));
- LinearHistogram linear_histogram("Linear", 1, 7, 8);
+ scoped_refptr<Histogram> linear_histogram =
+ LinearHistogram::LinearHistogramFactoryGet("Linear", 1, 7, 8);
// We also get a nice linear set of bucket ranges when we ask for it
for (int i = 0; i < 8; i++)
- EXPECT_EQ(i, linear_histogram.ranges(i));
- EXPECT_EQ(INT_MAX, linear_histogram.ranges(8));
+ EXPECT_EQ(i, linear_histogram->ranges(i));
+ EXPECT_EQ(INT_MAX, linear_histogram->ranges(8));
- LinearHistogram linear_broad_histogram("Linear widened", 2, 14, 8);
+ scoped_refptr<Histogram> linear_broad_histogram =
+ LinearHistogram::LinearHistogramFactoryGet(
+ "Linear widened", 2, 14, 8);
// ...but when the list has more space, then the ranges naturally spread out.
for (int i = 0; i < 8; i++)
- EXPECT_EQ(2 * i, linear_broad_histogram.ranges(i));
- EXPECT_EQ(INT_MAX, linear_broad_histogram.ranges(8));
+ EXPECT_EQ(2 * i, linear_broad_histogram->ranges(i));
+ EXPECT_EQ(INT_MAX, linear_broad_histogram->ranges(8));
- ThreadSafeHistogram threadsafe_histogram("ThreadSafe", 1, 32, 15);
+ scoped_refptr<Histogram> threadsafe_histogram =
+ ThreadSafeHistogram::ThreadSafeHistogramFactoryGet("ThreadSafe", 1, 32,
+ 15);
// When space is a little tight, we transition from linear to exponential.
// This is what happens in both the basic histogram, and the threadsafe
// variant (which is derived).
- EXPECT_EQ(0, threadsafe_histogram.ranges(0));
- EXPECT_EQ(1, threadsafe_histogram.ranges(1));
- EXPECT_EQ(2, threadsafe_histogram.ranges(2));
- EXPECT_EQ(3, threadsafe_histogram.ranges(3));
- EXPECT_EQ(4, threadsafe_histogram.ranges(4));
- EXPECT_EQ(5, threadsafe_histogram.ranges(5));
- EXPECT_EQ(6, threadsafe_histogram.ranges(6));
- EXPECT_EQ(7, threadsafe_histogram.ranges(7));
- EXPECT_EQ(9, threadsafe_histogram.ranges(8));
- EXPECT_EQ(11, threadsafe_histogram.ranges(9));
- EXPECT_EQ(14, threadsafe_histogram.ranges(10));
- EXPECT_EQ(17, threadsafe_histogram.ranges(11));
- EXPECT_EQ(21, threadsafe_histogram.ranges(12));
- EXPECT_EQ(26, threadsafe_histogram.ranges(13));
- EXPECT_EQ(32, threadsafe_histogram.ranges(14));
- EXPECT_EQ(INT_MAX, threadsafe_histogram.ranges(15));
+ EXPECT_EQ(0, threadsafe_histogram->ranges(0));
+ EXPECT_EQ(1, threadsafe_histogram->ranges(1));
+ EXPECT_EQ(2, threadsafe_histogram->ranges(2));
+ EXPECT_EQ(3, threadsafe_histogram->ranges(3));
+ EXPECT_EQ(4, threadsafe_histogram->ranges(4));
+ EXPECT_EQ(5, threadsafe_histogram->ranges(5));
+ EXPECT_EQ(6, threadsafe_histogram->ranges(6));
+ EXPECT_EQ(7, threadsafe_histogram->ranges(7));
+ EXPECT_EQ(9, threadsafe_histogram->ranges(8));
+ EXPECT_EQ(11, threadsafe_histogram->ranges(9));
+ EXPECT_EQ(14, threadsafe_histogram->ranges(10));
+ EXPECT_EQ(17, threadsafe_histogram->ranges(11));
+ EXPECT_EQ(21, threadsafe_histogram->ranges(12));
+ EXPECT_EQ(26, threadsafe_histogram->ranges(13));
+ EXPECT_EQ(32, threadsafe_histogram->ranges(14));
+ EXPECT_EQ(INT_MAX, threadsafe_histogram->ranges(15));
recorder.GetHistograms(&histograms);
EXPECT_EQ(5U, histograms.size());
@@ -159,21 +178,22 @@ TEST(HistogramTest, RangeTest) {
// Make sure histogram handles out-of-bounds data gracefully.
TEST(HistogramTest, BoundsTest) {
const size_t kBucketCount = 50;
- Histogram histogram("Bounded", 10, 100, kBucketCount);
+ scoped_refptr<Histogram> histogram = Histogram::HistogramFactoryGet("Bounded",
+ 10, 100, kBucketCount);
// Put two samples "out of bounds" above and below.
- histogram.Add(5);
- histogram.Add(-50);
+ histogram->Add(5);
+ histogram->Add(-50);
- histogram.Add(100);
- histogram.Add(10000);
+ histogram->Add(100);
+ histogram->Add(10000);
// Verify they landed in the underflow, and overflow buckets.
Histogram::SampleSet sample;
- histogram.SnapshotSample(&sample);
+ histogram->SnapshotSample(&sample);
EXPECT_EQ(2, sample.counts(0));
EXPECT_EQ(0, sample.counts(1));
- size_t array_size = histogram.bucket_count();
+ size_t array_size = histogram->bucket_count();
EXPECT_EQ(kBucketCount, array_size);
EXPECT_EQ(0, sample.counts(array_size - 2));
EXPECT_EQ(2, sample.counts(array_size - 1));
@@ -181,31 +201,32 @@ TEST(HistogramTest, BoundsTest) {
// Check to be sure samples land as expected is "correct" buckets.
TEST(HistogramTest, BucketPlacementTest) {
- Histogram histogram("Histogram", 1, 64, 8); // As mentioned in header file.
+ scoped_refptr<Histogram> histogram = Histogram::HistogramFactoryGet(
+ "Histogram", 1, 64, 8); // As mentioned in header file.
// Check that we got a nice exponential since there was enough rooom.
- EXPECT_EQ(0, histogram.ranges(0));
+ EXPECT_EQ(0, histogram->ranges(0));
int power_of_2 = 1;
for (int i = 1; i < 8; i++) {
- EXPECT_EQ(power_of_2, histogram.ranges(i));
+ EXPECT_EQ(power_of_2, histogram->ranges(i));
power_of_2 *= 2;
}
- EXPECT_EQ(INT_MAX, histogram.ranges(8));
+ EXPECT_EQ(INT_MAX, histogram->ranges(8));
// Add i+1 samples to the i'th bucket.
- histogram.Add(0);
+ histogram->Add(0);
power_of_2 = 1;
for (int i = 1; i < 8; i++) {
for (int j = 0; j <= i; j++)
- histogram.Add(power_of_2);
+ histogram->Add(power_of_2);
power_of_2 *= 2;
}
// Leave overflow bucket empty.
// Check to see that the bucket counts reflect our additions.
Histogram::SampleSet sample;
- histogram.SnapshotSample(&sample);
- EXPECT_EQ(INT_MAX, histogram.ranges(8));
+ histogram->SnapshotSample(&sample);
+ EXPECT_EQ(INT_MAX, histogram->ranges(8));
for (int i = 0; i < 8; i++)
EXPECT_EQ(i + 1, sample.counts(i));
}
diff --git a/base/message_loop.cc b/base/message_loop.cc
index ddca7dbf..64913e5 100644
--- a/base/message_loop.cc
+++ b/base/message_loop.cc
@@ -531,11 +531,12 @@ void MessageLoop::StartHistogrammer() {
if (enable_histogrammer_ && !message_histogram_.get()
&& StatisticsRecorder::WasStarted()) {
DCHECK(!thread_name_.empty());
- message_histogram_.reset(
- new LinearHistogram(("MsgLoop:" + thread_name_).c_str(),
+ message_histogram_ =
+ LinearHistogram::LinearHistogramFactoryGet(
+ ("MsgLoop:" + thread_name_),
kLeastNonZeroMessageId,
kMaxMessageId,
- kNumberOfDistinctMessagesDisplayed));
+ kNumberOfDistinctMessagesDisplayed);
message_histogram_->SetFlags(message_histogram_->kHexRangePrintingFlag);
message_histogram_->SetRangeDescriptions(event_descriptions_);
}
diff --git a/base/message_loop.h b/base/message_loop.h
index ff4531c..e45adde 100644
--- a/base/message_loop.h
+++ b/base/message_loop.h
@@ -397,7 +397,7 @@ class MessageLoop : public base::MessagePump::Delegate {
std::string thread_name_;
// A profiling histogram showing the counts of various messages and events.
- scoped_ptr<LinearHistogram> message_histogram_;
+ scoped_refptr<Histogram> message_histogram_;
// A null terminated list which creates an incoming_queue of tasks that are
// aquired under a mutex for processing on this instance's thread. These tasks
diff --git a/chrome/browser/chrome_browser_application_mac.mm b/chrome/browser/chrome_browser_application_mac.mm
index 48bef43..3aa31013 100644
--- a/chrome/browser/chrome_browser_application_mac.mm
+++ b/chrome/browser/chrome_browser_application_mac.mm
@@ -91,10 +91,11 @@ size_t BinForException(NSException* exception) {
}
void RecordExceptionWithUma(NSException* exception) {
- static LinearHistogram histogram("OSX.NSException", 0, kUnknownNSException,
- kUnknownNSException + 1);
- histogram.SetFlags(kUmaTargetedHistogramFlag);
- histogram.Add(BinForException(exception));
+ static scoped_refptr<Histogram> histogram =
+ LinearHistogram::LinearHistogramFactoryGet("OSX.NSException",
+ 0, kUnknownNSException, kUnknownNSException + 1);
+ histogram->SetFlags(kUmaTargetedHistogramFlag);
+ histogram->Add(BinForException(exception));
}
void Terminate() {
diff --git a/chrome/browser/diagnostics/sqlite_diagnostics.cc b/chrome/browser/diagnostics/sqlite_diagnostics.cc
index f3ca31d..b266002 100644
--- a/chrome/browser/diagnostics/sqlite_diagnostics.cc
+++ b/chrome/browser/diagnostics/sqlite_diagnostics.cc
@@ -43,9 +43,11 @@ class BasicSqliteErrrorHandler : public sql::ErrorDelegate {
static void RecordErrorInHistogram(int error) {
// The histogram values from sqlite result codes go currently from 1 to
// 26 currently but 50 gives them room to grow.
- static LinearHistogram histogram(kHistogramNames[unique], 1, 50, 51);
- histogram.SetFlags(kUmaTargetedHistogramFlag);
- histogram.Add(error);
+ static scoped_refptr<Histogram> histogram =
+ LinearHistogram::LinearHistogramFactoryGet(kHistogramNames[unique], 1,
+ 50, 51);
+ histogram->SetFlags(kUmaTargetedHistogramFlag);
+ histogram->Add(error);
}
};
diff --git a/chrome/browser/jankometer.cc b/chrome/browser/jankometer.cc
index 32b42ca..10d2f14 100644
--- a/chrome/browser/jankometer.cc
+++ b/chrome/browser/jankometer.cc
@@ -91,13 +91,15 @@ class JankObserver : public base::RefCountedThreadSafe<JankObserver>,
: MaxMessageDelay_(excessive_duration),
slow_processing_counter_(std::string("Chrome.SlowMsg") + thread_name),
queueing_delay_counter_(std::string("Chrome.DelayMsg") + thread_name),
- process_times_((std::string("Chrome.ProcMsgL ") +
- thread_name).c_str(), 1, 3600000, 50),
- total_times_((std::string("Chrome.TotalMsgL ") +
- thread_name).c_str(), 1, 3600000, 50),
total_time_watchdog_(excessive_duration, thread_name, watchdog_enable) {
- process_times_.SetFlags(kUmaTargetedHistogramFlag);
- total_times_.SetFlags(kUmaTargetedHistogramFlag);
+ process_times_ = Histogram::HistogramFactoryGet(
+ (std::string("Chrome.ProcMsgL ") + thread_name),
+ 1, 3600000, 50);
+ total_times_ = Histogram::HistogramFactoryGet(
+ (std::string("Chrome.TotalMsgL ") + thread_name),
+ 1, 3600000, 50);
+ process_times_->SetFlags(kUmaTargetedHistogramFlag);
+ total_times_->SetFlags(kUmaTargetedHistogramFlag);
}
// Attaches the observer to the current thread's message loop. You can only
@@ -137,8 +139,8 @@ class JankObserver : public base::RefCountedThreadSafe<JankObserver>,
TimeTicks now = TimeTicks::Now();
if (begin_process_message_ != TimeTicks()) {
TimeDelta processing_time = now - begin_process_message_;
- process_times_.AddTime(processing_time);
- total_times_.AddTime(queueing_time_ + processing_time);
+ process_times_->AddTime(processing_time);
+ total_times_->AddTime(queueing_time_ + processing_time);
}
if (now - begin_process_message_ >
TimeDelta::FromMilliseconds(kMaxMessageProcessingMs)) {
@@ -208,8 +210,8 @@ class JankObserver : public base::RefCountedThreadSafe<JankObserver>,
// Counters for the two types of jank we measure.
StatsCounter slow_processing_counter_; // Messages with long processing time.
StatsCounter queueing_delay_counter_; // Messages with long queueing delay.
- Histogram process_times_; // Time spent processing task.
- Histogram total_times_; // Total of queueing plus processing time.
+ scoped_refptr<Histogram> process_times_; // Time spent processing task.
+ scoped_refptr<Histogram> total_times_; // Total queueing plus processing.
JankWatchdog total_time_watchdog_; // Watching for excessive total_time.
DISALLOW_EVIL_CONSTRUCTORS(JankObserver);
diff --git a/chrome/browser/net/dns_host_info.cc b/chrome/browser/net/dns_host_info.cc
index 63eae34..755f54d 100644
--- a/chrome/browser/net/dns_host_info.cc
+++ b/chrome/browser/net/dns_host_info.cc
@@ -104,10 +104,11 @@ void DnsHostInfo::RemoveFromQueue() {
}
// Make a custom linear histogram for the region from 0 to boundary.
const size_t kBucketCount = 52;
- static LinearHistogram histogram("DNS.QueueRecycledUnder2", TimeDelta(),
- kBoundary, kBucketCount);
- histogram.SetFlags(kUmaTargetedHistogramFlag);
- histogram.AddTime(queue_duration_);
+ static scoped_refptr<Histogram> histogram =
+ LinearHistogram::LinearHistogramFactoryGet("DNS.QueueRecycledUnder2",
+ TimeDelta(), kBoundary, kBucketCount);
+ histogram->SetFlags(kUmaTargetedHistogramFlag);
+ histogram->AddTime(queue_duration_);
}
void DnsHostInfo::SetPendingDeleteState() {
diff --git a/chrome/browser/net/websocket_experiment/websocket_experiment_runner.cc b/chrome/browser/net/websocket_experiment/websocket_experiment_runner.cc
index 1dfa3d6..8d03b6f 100644
--- a/chrome/browser/net/websocket_experiment/websocket_experiment_runner.cc
+++ b/chrome/browser/net/websocket_experiment/websocket_experiment_runner.cc
@@ -28,31 +28,36 @@ static const int kWebSocketTimeSec = 10;
static const int kTimeBucketCount = 50;
// TODO(ukai): Use new thread-safe-reference-counted Histograms.
-#define UPDATE_HISTOGRAM(name, sample, min, max, bucket_count) do { \
- switch (task_state_) { \
- case STATE_RUN_WS: \
- { \
- static LinearHistogram counter( \
- "WebSocketExperiment.Basic." name, min, max, bucket_count); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.Add(sample); \
+#define UPDATE_HISTOGRAM(name, sample, min, max, bucket_count) do { \
+ switch (task_state_) { \
+ case STATE_RUN_WS: \
+ { \
+ static scoped_refptr<Histogram> counter = \
+ LinearHistogram::LinearHistogramFactoryGet(\
+ "WebSocketExperiment.Basic." name, \
+ min, max, bucket_count); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->Add(sample); \
} \
break; \
case STATE_RUN_WSS: \
{ \
- static LinearHistogram counter( \
- "WebSocketExperiment.Secure." name, min, max, bucket_count); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.Add(sample); \
+ static scoped_refptr<Histogram> counter = \
+ LinearHistogram::LinearHistogramFactoryGet(\
+ "WebSocketExperiment.Secure." name, \
+ min, max, bucket_count); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->Add(sample); \
} \
break; \
case STATE_RUN_WS_NODEFAULT_PORT: \
{ \
- static LinearHistogram counter( \
- "WebSocketExperiment.NoDefaultPort." name, \
- min, max, bucket_count); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.Add(sample); \
+ static scoped_refptr<Histogram> counter = \
+ LinearHistogram::LinearHistogramFactoryGet(\
+ "WebSocketExperiment.NoDefaultPort." name, \
+ min, max, bucket_count); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->Add(sample); \
} \
break; \
default: \
@@ -61,31 +66,36 @@ static const int kTimeBucketCount = 50;
} \
} while (0)
-#define UPDATE_HISTOGRAM_TIMES(name, sample, min, max, bucket_count) do { \
+#define UPDATE_HISTOGRAM_TIMES(name, sample, min, max, bucket_count) do { \
switch (task_state_) { \
case STATE_RUN_WS: \
{ \
- static Histogram counter( \
- "WebSocketExperiment.Basic." name, min, max, bucket_count); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.AddTime(sample); \
+ static scoped_refptr<Histogram> counter = \
+ Histogram::HistogramFactoryGet(\
+ "WebSocketExperiment.Basic." name, \
+ min, max, bucket_count); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->AddTime(sample); \
} \
break; \
case STATE_RUN_WSS: \
{ \
- static Histogram counter( \
- "WebSocketExperiment.Secure." name, min, max, bucket_count); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.AddTime(sample); \
+ static scoped_refptr<Histogram> counter = \
+ Histogram::HistogramFactoryGet(\
+ "WebSocketExperiment.Secure." name, \
+ min, max, bucket_count); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->AddTime(sample); \
} \
break; \
case STATE_RUN_WS_NODEFAULT_PORT: \
{ \
- static Histogram counter( \
- "WebSocketExperiment.NoDefaultPort." name, \
- min, max, bucket_count); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.AddTime(sample); \
+ static scoped_refptr<Histogram> counter = \
+ Histogram::HistogramFactoryGet(\
+ "WebSocketExperiment.NoDefaultPort." name, \
+ min, max, bucket_count); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->AddTime(sample); \
} \
break; \
default: \
diff --git a/chrome/browser/renderer_host/buffered_resource_handler.cc b/chrome/browser/renderer_host/buffered_resource_handler.cc
index f3ca82f..6cf4430 100644
--- a/chrome/browser/renderer_host/buffered_resource_handler.cc
+++ b/chrome/browser/renderer_host/buffered_resource_handler.cc
@@ -30,18 +30,23 @@ const int kMaxBytesToSniff = 512;
void RecordSnifferMetrics(bool sniffing_blocked,
bool we_would_like_to_sniff,
const std::string& mime_type) {
- static BooleanHistogram nosniff_usage("nosniff.usage");
- nosniff_usage.SetFlags(kUmaTargetedHistogramFlag);
- nosniff_usage.AddBoolean(sniffing_blocked);
+ static scoped_refptr<Histogram> nosniff_usage =
+ BooleanHistogram::BooleanHistogramFactoryGet("nosniff.usage");
+ nosniff_usage->SetFlags(kUmaTargetedHistogramFlag);
+ nosniff_usage->AddBoolean(sniffing_blocked);
if (sniffing_blocked) {
- static BooleanHistogram nosniff_otherwise("nosniff.otherwise");
- nosniff_otherwise.SetFlags(kUmaTargetedHistogramFlag);
- nosniff_otherwise.AddBoolean(we_would_like_to_sniff);
-
- static BooleanHistogram nosniff_empty_mime_type("nosniff.empty_mime_type");
- nosniff_empty_mime_type.SetFlags(kUmaTargetedHistogramFlag);
- nosniff_empty_mime_type.AddBoolean(mime_type.empty());
+ static scoped_refptr<Histogram> nosniff_otherwise =
+ BooleanHistogram::BooleanHistogramFactoryGet(
+ "nosniff.otherwise");
+ nosniff_otherwise->SetFlags(kUmaTargetedHistogramFlag);
+ nosniff_otherwise->AddBoolean(we_would_like_to_sniff);
+
+ static scoped_refptr<Histogram> nosniff_empty_mime_type =
+ BooleanHistogram::BooleanHistogramFactoryGet(
+ "nosniff.empty_mime_type");
+ nosniff_empty_mime_type->SetFlags(kUmaTargetedHistogramFlag);
+ nosniff_empty_mime_type->AddBoolean(mime_type.empty());
}
}
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
index a96146ce..3f559c0 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
@@ -69,9 +69,11 @@ enum SafeBrowsingBlockingPageEvent {
};
void RecordSafeBrowsingBlockingPageStats(SafeBrowsingBlockingPageEvent event) {
- static LinearHistogram histogram("interstial.safe_browsing", 0, 2, 3);
- histogram.SetFlags(kUmaTargetedHistogramFlag);
- histogram.Add(event);
+ static scoped_refptr<Histogram> histogram =
+ LinearHistogram::LinearHistogramFactoryGet("interstial.safe_browsing",
+ 1, 2, 3);
+ histogram->SetFlags(kUmaTargetedHistogramFlag);
+ histogram->Add(event);
}
} // namespace
diff --git a/chrome/browser/ssl/ssl_blocking_page.cc b/chrome/browser/ssl/ssl_blocking_page.cc
index 2de2d58c..d0f3d6a 100644
--- a/chrome/browser/ssl/ssl_blocking_page.cc
+++ b/chrome/browser/ssl/ssl_blocking_page.cc
@@ -34,9 +34,11 @@ enum SSLBlockingPageEvent {
};
void RecordSSLBlockingPageStats(SSLBlockingPageEvent event) {
- static LinearHistogram histogram("interstial.ssl", 0, 2, 3);
- histogram.SetFlags(kUmaTargetedHistogramFlag);
- histogram.Add(event);
+ static scoped_refptr<Histogram> histogram =
+ LinearHistogram::LinearHistogramFactoryGet(
+ "interstial.ssl", 1, 2, 3);
+ histogram->SetFlags(kUmaTargetedHistogramFlag);
+ histogram->Add(event);
}
} // namespace
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index 4cd9c6b..570b9a3 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -450,11 +450,12 @@ void ProfileSyncService::RemoveObserver(Observer* observer) {
}
void ProfileSyncService::SyncEvent(SyncEventCodes code) {
- static LinearHistogram histogram("Sync.EventCodes", MIN_SYNC_EVENT_CODE,
- MAX_SYNC_EVENT_CODE - 1,
- MAX_SYNC_EVENT_CODE);
- histogram.SetFlags(kUmaTargetedHistogramFlag);
- histogram.Add(code);
+ static scoped_refptr<Histogram> histogram =
+ LinearHistogram::LinearHistogramFactoryGet("Sync.EventCodes",
+ MIN_SYNC_EVENT_CODE + 1, MAX_SYNC_EVENT_CODE - 1,
+ MAX_SYNC_EVENT_CODE);
+ histogram->SetFlags(kUmaTargetedHistogramFlag);
+ histogram->Add(code);
}
bool ProfileSyncService::IsSyncEnabled() {
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc
index a4b36a6..d22f52a0 100644
--- a/chrome/renderer/render_thread.cc
+++ b/chrome/renderer/render_thread.cc
@@ -482,11 +482,17 @@ void RenderThread::SetCacheMode(bool enabled) {
static void* CreateHistogram(
const char *name, int min, int max, size_t buckets) {
- Histogram* histogram = new Histogram(name, min, max, buckets);
- if (histogram) {
- histogram->SetFlags(kUmaTargetedHistogramFlag);
- }
- return histogram;
+ if (min <= 0)
+ min = 1;
+ scoped_refptr<Histogram> histogram =
+ Histogram::HistogramFactoryGet(name, min, max, buckets);
+ // We verify this was not being destructed by setting a novel "PlannedLeak"
+ // flag and watching out for the flag in the destructor.
+ histogram->SetFlags(kUmaTargetedHistogramFlag | kPlannedLeakFlag);
+ // We'll end up leaking these histograms, unless there is some code hiding in
+ // there to do the dec-ref.
+ histogram->AddRef();
+ return histogram.get();
}
static void AddHistogramSample(void* hist, int sample) {
diff --git a/net/base/connection_type_histograms.cc b/net/base/connection_type_histograms.cc
index 6e4a929..d200bde 100644
--- a/net/base/connection_type_histograms.cc
+++ b/net/base/connection_type_histograms.cc
@@ -22,22 +22,24 @@ namespace net {
// expansion.
void UpdateConnectionTypeHistograms(ConnectionType type) {
static bool had_connection_type[NUM_OF_CONNECTION_TYPES];
- static LinearHistogram counter1("Net.HadConnectionType",
- 1, NUM_OF_CONNECTION_TYPES,
- NUM_OF_CONNECTION_TYPES + 1);
- static LinearHistogram counter2("Net.ConnectionTypeCount",
- 1, NUM_OF_CONNECTION_TYPES,
- NUM_OF_CONNECTION_TYPES + 1);
+ static scoped_refptr<Histogram> counter1 =
+ LinearHistogram::LinearHistogramFactoryGet("Net.HadConnectionType",
+ 1, NUM_OF_CONNECTION_TYPES,
+ NUM_OF_CONNECTION_TYPES + 1);
+ static scoped_refptr<Histogram> counter2 =
+ LinearHistogram::LinearHistogramFactoryGet("Net.ConnectionTypeCount",
+ 1, NUM_OF_CONNECTION_TYPES,
+ NUM_OF_CONNECTION_TYPES + 1);
if (type >= 0 && type < NUM_OF_CONNECTION_TYPES) {
if (!had_connection_type[type]) {
had_connection_type[type] = true;
- counter1.SetFlags(kUmaTargetedHistogramFlag);
- counter1.Add(type);
+ counter1->SetFlags(kUmaTargetedHistogramFlag);
+ counter1->Add(type);
}
}
- counter2.SetFlags(kUmaTargetedHistogramFlag);
- counter2.Add(type);
+ counter2->SetFlags(kUmaTargetedHistogramFlag);
+ counter2->Add(type);
}
} // namespace net
diff --git a/net/base/mime_sniffer.cc b/net/base/mime_sniffer.cc
index 07feb33..211cf8c 100644
--- a/net/base/mime_sniffer.cc
+++ b/net/base/mime_sniffer.cc
@@ -99,18 +99,6 @@
#include "googleurl/src/gurl.h"
#include "net/base/mime_util.h"
-namespace {
-
-class SnifferHistogram : public LinearHistogram {
- public:
- SnifferHistogram(const char* name, int array_size)
- : LinearHistogram(name, 0, array_size - 1, array_size) {
- SetFlags(kUmaTargetedHistogramFlag);
- }
-};
-
-} // namespace
-
namespace net {
// We aren't interested in looking at more than 512 bytes of content
@@ -218,6 +206,15 @@ static const MagicNumber kSniffableTags[] = {
MAGIC_HTML_TAG("p") // Mozilla
};
+static scoped_refptr<Histogram> UMASnifferHistogramGet(const char* name,
+ int array_size) {
+ scoped_refptr<Histogram> counter =
+ LinearHistogram::LinearHistogramFactoryGet(
+ name, 1, array_size - 1, array_size);
+ counter->SetFlags(kUmaTargetedHistogramFlag);
+ return counter;
+}
+
static bool MatchMagicNumber(const char* content, size_t size,
const MagicNumber* magic_entry,
std::string* result) {
@@ -273,22 +270,24 @@ static bool SniffForHTML(const char* content, size_t size,
if (!IsAsciiWhitespace(*pos))
break;
}
- static SnifferHistogram counter("mime_sniffer.kSniffableTags2",
- arraysize(kSniffableTags));
+ static scoped_refptr<Histogram> counter =
+ UMASnifferHistogramGet("mime_sniffer.kSniffableTags2",
+ arraysize(kSniffableTags));
// |pos| now points to first non-whitespace character (or at end).
return CheckForMagicNumbers(pos, end - pos,
kSniffableTags, arraysize(kSniffableTags),
- &counter, result);
+ counter.get(), result);
}
static bool SniffForMagicNumbers(const char* content, size_t size,
std::string* result) {
// Check our big table of Magic Numbers
- static SnifferHistogram counter("mime_sniffer.kMagicNumbers2",
- arraysize(kMagicNumbers));
+ static scoped_refptr<Histogram> counter =
+ UMASnifferHistogramGet("mime_sniffer.kMagicNumbers2",
+ arraysize(kMagicNumbers));
return CheckForMagicNumbers(content, size,
kMagicNumbers, arraysize(kMagicNumbers),
- &counter, result);
+ counter.get(), result);
}
// Byte order marks
@@ -320,8 +319,9 @@ static bool SniffXML(const char* content, size_t size, std::string* result) {
// We want to skip XML processing instructions (of the form "<?xml ...")
// and stop at the first "plain" tag, then make a decision on the mime-type
// based on the name (or possibly attributes) of that tag.
- static SnifferHistogram counter("mime_sniffer.kMagicXML2",
- arraysize(kMagicXML));
+ static scoped_refptr<Histogram> counter =
+ UMASnifferHistogramGet("mime_sniffer.kMagicXML2",
+ arraysize(kMagicXML));
const int kMaxTagIterations = 5;
for (int i = 0; i < kMaxTagIterations && pos < end; ++i) {
pos = reinterpret_cast<const char*>(memchr(pos, '<', end - pos));
@@ -341,7 +341,7 @@ static bool SniffXML(const char* content, size_t size, std::string* result) {
if (CheckForMagicNumbers(pos, end - pos,
kMagicXML, arraysize(kMagicXML),
- &counter, result))
+ counter.get(), result))
return true;
// TODO(evanm): handle RSS 1.0, which is an RDF format and more difficult
@@ -388,12 +388,13 @@ static char kByteLooksBinary[] = {
static bool LooksBinary(const char* content, size_t size) {
// First, we look for a BOM.
- static SnifferHistogram counter("mime_sniffer.kByteOrderMark2",
- arraysize(kByteOrderMark));
+ static scoped_refptr<Histogram> counter =
+ UMASnifferHistogramGet("mime_sniffer.kByteOrderMark2",
+ arraysize(kByteOrderMark));
std::string unused;
if (CheckForMagicNumbers(content, size,
kByteOrderMark, arraysize(kByteOrderMark),
- &counter, &unused)) {
+ counter.get(), &unused)) {
// If there is BOM, we think the buffer is not binary.
return false;
}
@@ -422,17 +423,18 @@ static bool IsUnknownMimeType(const std::string& mime_type) {
// Firefox rejects a mime type if it is exactly */*
"*/*",
};
- static SnifferHistogram counter("mime_sniffer.kUnknownMimeTypes2",
- arraysize(kUnknownMimeTypes) + 1);
+ static scoped_refptr<Histogram> counter =
+ UMASnifferHistogramGet("mime_sniffer.kUnknownMimeTypes2",
+ arraysize(kUnknownMimeTypes) + 1);
for (size_t i = 0; i < arraysize(kUnknownMimeTypes); ++i) {
if (mime_type == kUnknownMimeTypes[i]) {
- counter.Add(i);
+ counter->Add(i);
return true;
}
}
if (mime_type.find('/') == std::string::npos) {
// Firefox rejects a mime type if it does not contain a slash
- counter.Add(arraysize(kUnknownMimeTypes));
+ counter->Add(arraysize(kUnknownMimeTypes));
return true;
}
return false;
@@ -441,7 +443,8 @@ static bool IsUnknownMimeType(const std::string& mime_type) {
// Sniff a crx (chrome extension) file.
static bool SniffCRX(const char* content, size_t content_size, const GURL& url,
const std::string& type_hint, std::string* result) {
- static SnifferHistogram counter("mime_sniffer.kSniffCRX", 3);
+ static scoped_refptr<Histogram> counter =
+ UMASnifferHistogramGet("mime_sniffer.kSniffCRX", 3);
// Technically, the crx magic number is just Cr24, but the bytes after that
// are a version number which changes infrequently. Including it in the
@@ -459,7 +462,7 @@ static bool SniffCRX(const char* content, size_t content_size, const GURL& url,
const int kExtensionLength = arraysize(kCRXExtension) - 1; // ignore null
if (url.path().rfind(kCRXExtension, std::string::npos, kExtensionLength) ==
url.path().size() - kExtensionLength) {
- counter.Add(1);
+ counter->Add(1);
} else {
return false;
}
@@ -467,7 +470,7 @@ static bool SniffCRX(const char* content, size_t content_size, const GURL& url,
if (CheckForMagicNumbers(content, content_size,
kCRXMagicNumbers, arraysize(kCRXMagicNumbers),
NULL, result)) {
- counter.Add(2);
+ counter->Add(2);
} else {
return false;
}
@@ -476,15 +479,15 @@ static bool SniffCRX(const char* content, size_t content_size, const GURL& url,
}
bool ShouldSniffMimeType(const GURL& url, const std::string& mime_type) {
- static SnifferHistogram should_sniff_counter(
- "mime_sniffer.ShouldSniffMimeType2", 3);
+ static scoped_refptr<Histogram> should_sniff_counter =
+ UMASnifferHistogramGet("mime_sniffer.ShouldSniffMimeType2", 3);
// We are willing to sniff the mime type for HTTP, HTTPS, and FTP
bool sniffable_scheme = url.is_empty() ||
url.SchemeIs("http") ||
url.SchemeIs("https") ||
url.SchemeIs("ftp");
if (!sniffable_scheme) {
- should_sniff_counter.Add(1);
+ should_sniff_counter->Add(1);
return false;
}
@@ -501,23 +504,24 @@ bool ShouldSniffMimeType(const GURL& url, const std::string& mime_type) {
"text/xml",
"application/xml",
};
- static SnifferHistogram counter("mime_sniffer.kSniffableTypes2",
- arraysize(kSniffableTypes) + 1);
+ static scoped_refptr<Histogram> counter =
+ UMASnifferHistogramGet("mime_sniffer.kSniffableTypes2",
+ arraysize(kSniffableTypes) + 1);
for (size_t i = 0; i < arraysize(kSniffableTypes); ++i) {
if (mime_type == kSniffableTypes[i]) {
- counter.Add(i);
- should_sniff_counter.Add(2);
+ counter->Add(i);
+ should_sniff_counter->Add(2);
return true;
}
}
if (IsUnknownMimeType(mime_type)) {
// The web server didn't specify a content type or specified a mime
// type that we ignore.
- counter.Add(arraysize(kSniffableTypes));
- should_sniff_counter.Add(2);
+ counter->Add(arraysize(kSniffableTypes));
+ should_sniff_counter->Add(2);
return true;
}
- should_sniff_counter.Add(1);
+ should_sniff_counter->Add(1);
return false;
}
diff --git a/net/base/sdch_manager.cc b/net/base/sdch_manager.cc
index b30a171..126a1b6 100644
--- a/net/base/sdch_manager.cc
+++ b/net/base/sdch_manager.cc
@@ -32,10 +32,11 @@ SdchManager* SdchManager::Global() {
// static
void SdchManager::SdchErrorRecovery(ProblemCodes problem) {
- static LinearHistogram histogram("Sdch3.ProblemCodes_4", MIN_PROBLEM_CODE,
- MAX_PROBLEM_CODE - 1, MAX_PROBLEM_CODE);
- histogram.SetFlags(kUmaTargetedHistogramFlag);
- histogram.Add(problem);
+ static scoped_refptr<Histogram> histogram =
+ LinearHistogram::LinearHistogramFactoryGet("Sdch3.ProblemCodes_4",
+ MIN_PROBLEM_CODE + 1, MAX_PROBLEM_CODE - 1, MAX_PROBLEM_CODE);
+ histogram->SetFlags(kUmaTargetedHistogramFlag);
+ histogram->Add(problem);
}
// static
diff --git a/net/disk_cache/histogram_macros.h b/net/disk_cache/histogram_macros.h
index 6ff66ea..6d63dc8 100644
--- a/net/disk_cache/histogram_macros.h
+++ b/net/disk_cache/histogram_macros.h
@@ -26,9 +26,11 @@
UMA_HISTOGRAM_TIMES(name, Time::Now() - initial_time)
#define UMA_HISTOGRAM_CACHE_ERROR(name, sample) do { \
- static LinearHistogram counter((name), 0, 49, 50); \
- counter.SetFlags(kUmaTargetedHistogramFlag); \
- counter.Add(sample); \
+ static scoped_refptr<Histogram> counter = \
+ LinearHistogram::LinearHistogramFactoryGet(\
+ (name), 1, 49, 50); \
+ counter->SetFlags(kUmaTargetedHistogramFlag); \
+ counter->Add(sample); \
} while (0)
#ifdef NET_DISK_CACHE_BACKEND_IMPL_CC_
diff --git a/net/disk_cache/stats.cc b/net/disk_cache/stats.cc
index a351a6c..e69ea00 100644
--- a/net/disk_cache/stats.cc
+++ b/net/disk_cache/stats.cc
@@ -138,7 +138,8 @@ bool Stats::Init(BackendImpl* backend, uint32* storage_addr) {
backend->ShouldReportAgain()) {
// Stats may be reused when the cache is re-created, but we want only one
// histogram at any given time.
- size_histogram_.reset(new StatsHistogram("DiskCache.SizeStats"));
+ size_histogram_ =
+ StatsHistogram::StatsHistogramFactoryGet("DiskCache.SizeStats");
size_histogram_->Init(this);
}
}
diff --git a/net/disk_cache/stats.h b/net/disk_cache/stats.h
index 1dcd39f..13536b1 100644
--- a/net/disk_cache/stats.h
+++ b/net/disk_cache/stats.h
@@ -84,7 +84,7 @@ class Stats {
uint32 storage_addr_;
int data_sizes_[kDataSizesLength];
int64 counters_[MAX_COUNTER];
- scoped_ptr<StatsHistogram> size_histogram_;
+ scoped_refptr<StatsHistogram> size_histogram_;
DISALLOW_COPY_AND_ASSIGN(Stats);
};
diff --git a/net/disk_cache/stats_histogram.cc b/net/disk_cache/stats_histogram.cc
index f605934..e6eaf90 100644
--- a/net/disk_cache/stats_histogram.cc
+++ b/net/disk_cache/stats_histogram.cc
@@ -12,6 +12,37 @@ namespace disk_cache {
// Static.
const Stats* StatsHistogram::stats_ = NULL;
+scoped_refptr<StatsHistogram> StatsHistogram::StatsHistogramFactoryGet(
+ const std::string& name) {
+ scoped_refptr<Histogram> histogram(NULL);
+
+ Sample minimum = 1;
+ Sample maximum = disk_cache::Stats::kDataSizesLength - 1;
+ size_t bucket_count = disk_cache::Stats::kDataSizesLength;
+
+ if (StatisticsRecorder::FindHistogram(name, &histogram)) {
+ DCHECK(histogram.get() != NULL);
+ } else {
+ histogram = new StatsHistogram(name, minimum, maximum, bucket_count);
+ scoped_refptr<Histogram> registered_histogram(NULL);
+ StatisticsRecorder::FindHistogram(name, &registered_histogram);
+ if (registered_histogram.get() != NULL &&
+ registered_histogram.get() != histogram.get())
+ histogram = registered_histogram;
+ }
+
+ DCHECK(HISTOGRAM == histogram->histogram_type());
+ DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count));
+
+ // We're preparing for an otherwise unsafe upcast by ensuring we have the
+ // proper class type.
+ Histogram* temp_histogram = histogram.get();
+ StatsHistogram* temp_stats_histogram =
+ static_cast<StatsHistogram*>(temp_histogram);
+ scoped_refptr<StatsHistogram> return_histogram = temp_stats_histogram;
+ return return_histogram;
+}
+
bool StatsHistogram::Init(const Stats* stats) {
DCHECK(stats);
if (stats_)
diff --git a/net/disk_cache/stats_histogram.h b/net/disk_cache/stats_histogram.h
index 8db3bb3..995d486 100644
--- a/net/disk_cache/stats_histogram.h
+++ b/net/disk_cache/stats_histogram.h
@@ -5,6 +5,8 @@
#ifndef NET_DISK_CACHE_STATS_HISTOGRAM_H_
#define NET_DISK_CACHE_STATS_HISTOGRAM_H_
+#include <string>
+
#include "base/histogram.h"
namespace disk_cache {
@@ -14,6 +16,10 @@ class Stats;
// This class provides support for sending the disk cache size stats as a UMA
// histogram. We'll provide our own storage and management for the data, and a
// SampleSet with a copy of our data.
+//
+// Class derivation of Histogram "deprecated," and should not be copied, and
+// may eventually go away.
+//
class StatsHistogram : public Histogram {
public:
class StatsSamples : public SampleSet {
@@ -23,10 +29,14 @@ class StatsHistogram : public Histogram {
}
};
- explicit StatsHistogram(const char* name)
- : Histogram(name, 1, 1, 2), init_(false) {}
+ explicit StatsHistogram(const std::string& name, Sample minimum,
+ Sample maximum, size_t bucket_count)
+ : Histogram(name, minimum, maximum, bucket_count), init_(false) {}
~StatsHistogram();
+ static scoped_refptr<StatsHistogram>
+ StatsHistogramFactoryGet(const std::string& name);
+
// We'll be reporting data from the given set of cache stats.
bool Init(const Stats* stats);
@@ -35,6 +45,8 @@ class StatsHistogram : public Histogram {
virtual void SnapshotSample(SampleSet* sample) const;
private:
+ friend class Histogram;
+
bool init_;
static const Stats* stats_;
DISALLOW_COPY_AND_ASSIGN(StatsHistogram);
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc
index 1dfc99b..8014d07 100644
--- a/net/ftp/ftp_network_transaction.cc
+++ b/net/ftp/ftp_network_transaction.cc
@@ -1162,21 +1162,23 @@ void FtpNetworkTransaction::RecordDataConnectionError(int result) {
break;
};
static bool had_error_type[NUM_OF_NET_ERROR_TYPES];
- static LinearHistogram error_flagged("Net.FtpDataConnectionErrorHappened",
- 1, NUM_OF_NET_ERROR_TYPES,
- NUM_OF_NET_ERROR_TYPES + 1);
- static LinearHistogram error_counter("Net.FtpDataConnectionErrorCount",
- 1, NUM_OF_NET_ERROR_TYPES,
- NUM_OF_NET_ERROR_TYPES + 1);
+ static scoped_refptr<Histogram> error_flagged =
+ LinearHistogram::LinearHistogramFactoryGet(
+ "Net.FtpDataConnectionErrorHappened",
+ 1, NUM_OF_NET_ERROR_TYPES, NUM_OF_NET_ERROR_TYPES + 1);
+ static scoped_refptr<Histogram> error_counter =
+ LinearHistogram::LinearHistogramFactoryGet(
+ "Net.FtpDataConnectionErrorCount",
+ 1, NUM_OF_NET_ERROR_TYPES, NUM_OF_NET_ERROR_TYPES + 1);
DCHECK(type >= 0 && type < NUM_OF_NET_ERROR_TYPES);
if (!had_error_type[type]) {
had_error_type[type] = true;
- error_flagged.SetFlags(kUmaTargetedHistogramFlag);
- error_flagged.Add(type);
+ error_flagged->SetFlags(kUmaTargetedHistogramFlag);
+ error_flagged->Add(type);
}
- error_counter.SetFlags(kUmaTargetedHistogramFlag);
- error_counter.Add(type);
+ error_counter->SetFlags(kUmaTargetedHistogramFlag);
+ error_counter->Add(type);
}
} // namespace net
diff --git a/net/ftp/ftp_server_type_histograms.cc b/net/ftp/ftp_server_type_histograms.cc
index 3f419a8..60ab9b9 100644
--- a/net/ftp/ftp_server_type_histograms.cc
+++ b/net/ftp/ftp_server_type_histograms.cc
@@ -22,22 +22,24 @@ namespace net {
// expansion.
void UpdateFtpServerTypeHistograms(FtpServerType type) {
static bool had_server_type[NUM_OF_SERVER_TYPES];
- static LinearHistogram counter1("Net.HadFtpServerType",
- 1, NUM_OF_SERVER_TYPES,
- NUM_OF_SERVER_TYPES + 1);
- static LinearHistogram counter2("Net.FtpServerTypeCount",
- 1, NUM_OF_SERVER_TYPES,
- NUM_OF_SERVER_TYPES + 1);
+ static scoped_refptr<Histogram> counter1 =
+ LinearHistogram::LinearHistogramFactoryGet("Net.HadFtpServerType",
+ 1, NUM_OF_SERVER_TYPES,
+ NUM_OF_SERVER_TYPES + 1);
+ static scoped_refptr<Histogram> counter2 =
+ LinearHistogram::LinearHistogramFactoryGet("Net.FtpServerTypeCount",
+ 1, NUM_OF_SERVER_TYPES,
+ NUM_OF_SERVER_TYPES + 1);
if (type >= 0 && type < NUM_OF_SERVER_TYPES) {
if (!had_server_type[type]) {
had_server_type[type] = true;
- counter1.SetFlags(kUmaTargetedHistogramFlag);
- counter1.Add(type);
+ counter1->SetFlags(kUmaTargetedHistogramFlag);
+ counter1->Add(type);
}
}
- counter2.SetFlags(kUmaTargetedHistogramFlag);
- counter2.Add(type);
+ counter2->SetFlags(kUmaTargetedHistogramFlag);
+ counter2->Add(type);
}
} // namespace net
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index bdf3e3d..7ca82e38 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -996,18 +996,22 @@ void HttpNetworkTransaction::LogTCPConnectedMetrics(
100);
}
- static LinearHistogram tcp_socket_type_counter(
- "Net.TCPSocketType",
- 0, ClientSocketHandle::NUM_TYPES, ClientSocketHandle::NUM_TYPES + 1);
- tcp_socket_type_counter.SetFlags(kUmaTargetedHistogramFlag);
- tcp_socket_type_counter.Add(handle.reuse_type());
+ static scoped_refptr<Histogram> tcp_socket_type_counter =
+ LinearHistogram::LinearHistogramFactoryGet(
+ "Net.TCPSocketType",
+ 1, ClientSocketHandle::NUM_TYPES, ClientSocketHandle::NUM_TYPES + 1);
+ tcp_socket_type_counter->SetFlags(kUmaTargetedHistogramFlag);
+ tcp_socket_type_counter->Add(handle.reuse_type());
if (use_late_binding_histogram) {
- static LinearHistogram tcp_socket_type_counter2(
- FieldTrial::MakeName("Net.TCPSocketType", "SocketLateBinding").data(),
- 0, ClientSocketHandle::NUM_TYPES, ClientSocketHandle::NUM_TYPES + 1);
- tcp_socket_type_counter2.SetFlags(kUmaTargetedHistogramFlag);
- tcp_socket_type_counter2.Add(handle.reuse_type());
+ static scoped_refptr<Histogram> tcp_socket_type_counter2 =
+ LinearHistogram::LinearHistogramFactoryGet(
+ FieldTrial::MakeName("Net.TCPSocketType",
+ "SocketLateBinding").data(),
+ 1, ClientSocketHandle::NUM_TYPES,
+ ClientSocketHandle::NUM_TYPES + 1);
+ tcp_socket_type_counter2->SetFlags(kUmaTargetedHistogramFlag);
+ tcp_socket_type_counter2->Add(handle.reuse_type());
}
UMA_HISTOGRAM_CLIPPED_TIMES(
@@ -1065,19 +1069,22 @@ void HttpNetworkTransaction::LogIOErrorMetrics(
static const bool use_late_binding_histogram =
!FieldTrial::MakeName("", "SocketLateBinding").empty();
- static LinearHistogram io_error_socket_type_counter(
- "Net.IOError_SocketReuseType",
- 0, ClientSocketHandle::NUM_TYPES, ClientSocketHandle::NUM_TYPES + 1);
- io_error_socket_type_counter.SetFlags(kUmaTargetedHistogramFlag);
- io_error_socket_type_counter.Add(handle.reuse_type());
+ static scoped_refptr<Histogram> io_error_socket_type_counter =
+ LinearHistogram::LinearHistogramFactoryGet(
+ "Net.IOError_SocketReuseType",
+ 1, ClientSocketHandle::NUM_TYPES, ClientSocketHandle::NUM_TYPES + 1);
+ io_error_socket_type_counter->SetFlags(kUmaTargetedHistogramFlag);
+ io_error_socket_type_counter->Add(handle.reuse_type());
if (use_late_binding_histogram) {
- static LinearHistogram io_error_socket_type_counter(
- FieldTrial::MakeName("Net.IOError_SocketReuseType",
- "SocketLateBinding").data(),
- 0, ClientSocketHandle::NUM_TYPES, ClientSocketHandle::NUM_TYPES + 1);
- io_error_socket_type_counter.SetFlags(kUmaTargetedHistogramFlag);
- io_error_socket_type_counter.Add(handle.reuse_type());
+ static scoped_refptr<Histogram> io_error_socket_type_counter =
+ LinearHistogram::LinearHistogramFactoryGet(
+ FieldTrial::MakeName("Net.IOError_SocketReuseType",
+ "SocketLateBinding").data(),
+ 1, ClientSocketHandle::NUM_TYPES,
+ ClientSocketHandle::NUM_TYPES + 1);
+ io_error_socket_type_counter->SetFlags(kUmaTargetedHistogramFlag);
+ io_error_socket_type_counter->Add(handle.reuse_type());
}
switch (handle.reuse_type()) {
diff --git a/net/socket_stream/socket_stream_metrics.cc b/net/socket_stream/socket_stream_metrics.cc
index f7a55a4..6220eb5 100644
--- a/net/socket_stream/socket_stream_metrics.cc
+++ b/net/socket_stream/socket_stream_metrics.cc
@@ -83,19 +83,21 @@ void SocketStreamMetrics::OnClose() {
}
void SocketStreamMetrics::CountProtocolType(ProtocolType protocol_type) {
- static LinearHistogram counter("Net.SocketStream.ProtocolType",
- 0, NUM_PROTOCOL_TYPES,
- NUM_PROTOCOL_TYPES + 1);
- counter.SetFlags(kUmaTargetedHistogramFlag);
- counter.Add(protocol_type);
+ static scoped_refptr<Histogram> counter =
+ LinearHistogram::LinearHistogramFactoryGet(
+ "Net.SocketStream.ProtocolType",
+ 0, NUM_PROTOCOL_TYPES, NUM_PROTOCOL_TYPES + 1);
+ counter->SetFlags(kUmaTargetedHistogramFlag);
+ counter->Add(protocol_type);
}
void SocketStreamMetrics::CountConnectionType(ConnectionType connection_type) {
- static LinearHistogram counter("Net.SocketStream.ConnectionType",
- 1, NUM_CONNECTION_TYPES,
- NUM_CONNECTION_TYPES + 1);
- counter.SetFlags(kUmaTargetedHistogramFlag);
- counter.Add(connection_type);
+ static scoped_refptr<Histogram> counter =
+ LinearHistogram::LinearHistogramFactoryGet(
+ "Net.SocketStream.ConnectionType",
+ 1, NUM_CONNECTION_TYPES, NUM_CONNECTION_TYPES + 1);
+ counter->SetFlags(kUmaTargetedHistogramFlag);
+ counter->Add(connection_type);
}