Index: base/histogram.h |
=================================================================== |
--- base/histogram.h (revision 33932) |
+++ base/histogram.h (working copy) |
@@ -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; |
-class Histogram { |
+namespace disk_cache { |
+ class StatsHistogram; |
+}; // namespace disk_cache |
+ |
+ |
+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 @@ |
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 @@ |
int64 square_sum_; // sum of squares of samples. |
}; |
//---------------------------------------------------------------------------- |
+ // 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); |
- 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(); |
+ void Add(int value); |
- 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 @@ |
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 @@ |
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 @@ |
// 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 @@ |
// 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 @@ |
// sample. |
SampleSet sample_; |
- // Indicate if successfully registered. |
- bool registered_; |
- |
DISALLOW_COPY_AND_ASSIGN(Histogram); |
}; |
@@ -446,24 +531,30 @@ |
// 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); |
+ virtual ClassType histogram_type() const { return LINEAR_HISTOGRAM; } |
- LinearHistogram(const char* name, base::TimeDelta minimum, |
- base::TimeDelta maximum, size_t bucket_count); |
- ~LinearHistogram() {} |
- |
// 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 @@ |
// 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); |
- void AddBoolean(bool value) { Add(value ? 1 : 0); } |
+ virtual ClassType histogram_type() const { return BOOLEAN_HISTOGRAM; } |
+ 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 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 StatisticsRecorder { |
public: |
- typedef std::vector<Histogram*> Histograms; |
+ typedef std::vector<scoped_refptr<Histogram> > Histograms; |
StatisticsRecorder(); |
@@ -542,10 +646,7 @@ |
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,9 +657,17 @@ |
// 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; } |
// GetSnapshot copies some of the pointers to registered histograms into the |
@@ -570,7 +679,7 @@ |
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_; |