Index: base/metrics/histogram.h |
=================================================================== |
--- base/metrics/histogram.h (revision 148055) |
+++ base/metrics/histogram.h (working copy) |
@@ -9,14 +9,31 @@ |
// It supports calls to accumulate either time intervals (which are processed |
// as integral number of milliseconds), or arbitrary integral units. |
-// The default layout of buckets is exponential. For example, buckets might |
-// contain (sequentially) the count of values in the following intervals: |
+// For Histogram(exponential histogram), LinearHistogram and CustomHistogram, |
+// the minimum for a declared range is 1 (instead of 0), while the maximum is |
+// (HistogramBase::kSampleType_MAX - 1). Currently you can declare histograms |
+// with ranges exceeding those limits (e.g. 0 as minimal or |
+// HistogramBase::kSampleType_MAX as maximal), but those excesses will be |
+// silently clamped to those limits (for backwards compatibility with existing |
+// code). Best practice is to not exceed the limits. |
+ |
+// For Histogram and LinearHistogram, the maximum for a declared range should |
+// always be larger (not equal) than minmal range. Zero and |
+// HistogramBase::kSampleType_MAX are implicitly added as first and last ranges, |
+// so the smallest legal bucket_count is 3. However CustomHistogram can have |
+// bucket count as 2 (when you give a custom ranges vector containing only 1 |
+// range). |
+// For these 3 kinds of histograms, the max bucket count is always |
+// (Histogram::kBucketCount_MAX - 1). |
+ |
+// The buckets layout of class Histogram is exponential. For example, buckets |
+// might contain (sequentially) the count of values in the following intervals: |
// [0,1), [1,2), [2,4), [4,8), [8,16), [16,32), [32,64), [64,infinity) |
// That bucket allocation would actually result from construction of a histogram |
// for values between 1 and 64, with 8 buckets, such as: |
-// Histogram count(L"some name", 1, 64, 8); |
+// Histogram count("some name", 1, 64, 8); |
// Note that the underflow bucket [0,1) and the overflow bucket [64,infinity) |
-// are not counted by the constructor in the user supplied "bucket_count" |
+// are also counted by the constructor in the user supplied "bucket_count" |
// argument. |
// The above example has an exponential ratio of 2 (doubling the bucket width |
// in each consecutive bucket. The Histogram class automatically calculates |
@@ -28,8 +45,9 @@ |
// at the low end of the histogram scale, but allows the histogram to cover a |
// gigantic range with the addition of very few buckets. |
-// Histograms use a pattern involving a function static variable, that is a |
-// pointer to a histogram. This static is explicitly initialized on any thread |
+// Usually we use macros to define and use a histogram. These macros use a |
+// pattern involving a function static variable, that is a pointer to a |
+// histogram. This static is explicitly initialized on any thread |
// that detects a uninitialized (NULL) pointer. The potentially racy |
// initialization is not a problem as it is always set to point to the same |
// value (i.e., the FactoryGet always returns the same value). FactoryGet |
@@ -177,9 +195,10 @@ |
boundary_value + 1, base::Histogram::kNoFlags)) |
// Support histograming of an enumerated value. Samples should be one of the |
-// std::vector<int> list provided via |custom_ranges|. You can use the helper |
-// function |base::CustomHistogram::ArrayToCustomRanges(samples, num_samples)| |
-// to transform a C-style array of valid sample values to a std::vector<int>. |
+// std::vector<int> list provided via |custom_ranges|. See comments above |
+// CustomRanges::FactoryGet about the requirement of |custom_ranges|. |
+// You can use the helper function CustomHistogram::ArrayToCustomRanges to |
+// transform a C-style array of valid sample values to a std::vector<int>. |
#define HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \ |
STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \ |
base::CustomHistogram::FactoryGet(name, custom_ranges, \ |
@@ -338,13 +357,13 @@ |
LINEAR_HISTOGRAM, |
BOOLEAN_HISTOGRAM, |
CUSTOM_HISTOGRAM, |
- NOT_VALID_IN_RENDERER |
+ NOT_VALID_IN_RENDERER, |
}; |
enum BucketLayout { |
EXPONENTIAL, |
LINEAR, |
- CUSTOM |
+ CUSTOM, |
}; |
enum Flags { |
@@ -381,17 +400,17 @@ |
class BASE_EXPORT SampleSet { |
public: |
- explicit SampleSet(); |
+ explicit SampleSet(size_t size); |
+ SampleSet(); |
~SampleSet(); |
- // Adjust size of counts_ for use with given histogram. |
- void Resize(const Histogram& histogram); |
- void CheckSize(const Histogram& histogram) const; |
+ void Resize(size_t size); |
// Accessor for histogram to make routine additions. |
void Accumulate(Sample value, Count count, size_t index); |
// Accessor methods. |
+ size_t size() const { return counts_.size(); } |
Count counts(size_t i) const { return counts_[i]; } |
Count TotalCount() const; |
int64 sum() const { return sum_; } |
@@ -447,10 +466,16 @@ |
base::TimeDelta maximum, |
size_t bucket_count, |
Flags flags); |
+ |
// Time call for use with DHISTOGRAM*. |
// Returns TimeTicks::Now() in debug and TimeTicks() in release build. |
static TimeTicks DebugNow(); |
+ static void InitializeBucketRanges(Sample minimum, |
+ Sample maximum, |
+ size_t bucket_count, |
+ BucketRanges* ranges); |
+ |
virtual void Add(Sample value) OVERRIDE; |
// This method is an interface, used only by BooleanHistogram. |
@@ -507,43 +532,44 @@ |
Sample declared_min() const { return declared_min_; } |
Sample declared_max() const { return declared_max_; } |
virtual Sample ranges(size_t i) const; |
- uint32 range_checksum() const { return range_checksum_; } |
virtual size_t bucket_count() const; |
- BucketRanges* bucket_ranges() const { return bucket_ranges_; } |
- void set_bucket_ranges(BucketRanges* bucket_ranges) { |
- bucket_ranges_ = bucket_ranges; |
- } |
+ const BucketRanges* bucket_ranges() const { return bucket_ranges_; } |
+ |
// Snapshot the current complete set of sample data. |
// Override with atomic/locked snapshot if needed. |
virtual void SnapshotSample(SampleSet* sample) const; |
- virtual bool HasConstructorArguments(Sample minimum, Sample maximum, |
- size_t bucket_count); |
- |
- virtual bool HasConstructorTimeDeltaArguments(TimeDelta minimum, |
- TimeDelta maximum, |
- size_t bucket_count); |
- // Return true iff the range_checksum_ matches current |ranges_| vector in |
- // |bucket_ranges_|. |
- bool HasValidRangeChecksum() const; |
- |
+ virtual bool HasConstructionArguments(Sample minimum, |
+ Sample maximum, |
+ size_t bucket_count); |
protected: |
- Histogram(const std::string& name, Sample minimum, |
- Sample maximum, size_t bucket_count); |
- Histogram(const std::string& name, TimeDelta minimum, |
- TimeDelta maximum, size_t bucket_count); |
+ // |bucket_count| and |ranges| should contain the underflow and overflow |
+ // buckets. See top comments for example. |
+ Histogram(const std::string& name, |
+ Sample minimum, |
+ Sample maximum, |
+ size_t bucket_count, |
+ const BucketRanges* ranges); |
virtual ~Histogram(); |
+ // This function validates histogram construction arguments. It returns false |
+ // if some of the arguments are totally bad. |
+ // Note. Currently it allow some bad input, e.g. 0 as minimum, but silently |
+ // converts it to good input: 1. |
+ // TODO(kaiwang): Be more restrict and return false for any bad input, and |
+ // make this a readonly validating function. |
+ static bool InspectConstructionArguments(const std::string& name, |
+ Sample* minimum, |
+ Sample* maximum, |
+ size_t* bucket_count); |
+ |
// Serialize the histogram's ranges to |*pickle|, returning true on success. |
// Most subclasses can leave this no-op implementation, but some will want to |
// override it, especially if the ranges cannot be re-derived from other |
// serialized parameters. |
virtual bool SerializeRanges(Pickle* pickle) const; |
- // Initialize ranges_ mapping in bucket_ranges_. |
- void InitializeBucketRange(); |
- |
// Method to override to skip the display of the i'th bucket if it's empty. |
virtual bool PrintEmptyBucket(size_t index) const; |
@@ -555,9 +581,6 @@ |
// Get normalized size, relative to the ranges(i). |
virtual double GetBucketSize(Count current, size_t i) const; |
- // Recalculate range_checksum_. |
- void ResetRangeChecksum(); |
- |
// Return a string description of what goes in a given bucket. |
// Most commonly this is the numeric value, but in derived classes it may |
// be a name (or string description) given to the bucket. |
@@ -569,18 +592,6 @@ |
// Update all our internal data, including histogram |
virtual void Accumulate(Sample value, Count count, size_t index); |
- //---------------------------------------------------------------------------- |
- // Accessors for derived classes. |
- //---------------------------------------------------------------------------- |
- void SetBucketRange(size_t i, Sample value); |
- |
- // Validate that ranges_ in bucket_ranges_ was created sensibly (top and |
- // bottom range values relate properly to the declared_min_ and |
- // declared_max_). |
- bool ValidateBucketRanges() const; |
- |
- virtual uint32 CalculateRangeChecksum() const; |
- |
private: |
// Allow tests to corrupt our innards for testing purposes. |
FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptBucketBounds); |
@@ -589,13 +600,8 @@ |
FRIEND_TEST_ALL_PREFIXES(HistogramTest, Crc32TableTest); |
friend class StatisticsRecorder; // To allow it to delete duplicates. |
+ friend class StatisticsRecorderTest; |
- // Post constructor initialization. |
- void Initialize(); |
- |
- // Checksum function for accumulating range values into a checksum. |
- static uint32 Crc32(uint32 sum, Sample range); |
- |
//---------------------------------------------------------------------------- |
// Helpers for emitting Ascii graphic. Each method appends data to output. |
@@ -625,11 +631,8 @@ |
void WriteAsciiBucketGraph(double current_size, double max_size, |
std::string* output) const; |
- //---------------------------------------------------------------------------- |
- // Table for generating Crc32 values. |
- static const uint32 kCrcTable[256]; |
- //---------------------------------------------------------------------------- |
- // Invariant values set at/near construction time |
+ // Does not own this object. Should get from StatisticsRecorder. |
+ const BucketRanges* bucket_ranges_; |
Sample declared_min_; // Less than this goes into counts_[0] |
Sample declared_max_; // Over this goes into counts_[bucket_count_ - 1]. |
@@ -638,17 +641,6 @@ |
// Flag the histogram for recording by UMA via metric_services.h. |
Flags flags_; |
- // For each index, show the least value that can be stored in the |
- // corresponding bucket. We also append one extra element in this array, |
- // containing kSampleType_MAX, to make calculations easy. |
- // The dimension of ranges_ in bucket_ranges_ is bucket_count + 1. |
- BucketRanges* bucket_ranges_; |
- |
- // For redundancy, we store a checksum of all the sample ranges when ranges |
- // are generated. If ever there is ever a difference, then the histogram must |
- // have been corrupted. |
- uint32 range_checksum_; |
- |
// Finally, provide the state that changes with the addition of each new |
// sample. |
SampleSet sample_; |
@@ -677,6 +669,11 @@ |
size_t bucket_count, |
Flags flags); |
+ static void InitializeBucketRanges(Sample minimum, |
+ Sample maximum, |
+ size_t bucket_count, |
+ BucketRanges* ranges); |
+ |
// Overridden from Histogram: |
virtual ClassType histogram_type() const OVERRIDE; |
@@ -686,14 +683,12 @@ |
const DescriptionPair descriptions[]) OVERRIDE; |
protected: |
- LinearHistogram(const std::string& name, Sample minimum, |
- Sample maximum, size_t bucket_count); |
+ LinearHistogram(const std::string& name, |
+ Sample minimum, |
+ Sample maximum, |
+ size_t bucket_count, |
+ const BucketRanges* ranges); |
- LinearHistogram(const std::string& name, TimeDelta minimum, |
- TimeDelta maximum, size_t bucket_count); |
- |
- // Initialize ranges_ mapping in bucket_ranges_. |
- void InitializeBucketRange(); |
virtual double GetBucketSize(Count current, size_t i) const OVERRIDE; |
// If we have a description for a bucket, then return that. Otherwise |
@@ -726,7 +721,7 @@ |
virtual void AddBoolean(bool value) OVERRIDE; |
private: |
- explicit BooleanHistogram(const std::string& name); |
+ BooleanHistogram(const std::string& name, const BucketRanges* ranges); |
DISALLOW_COPY_AND_ASSIGN(BooleanHistogram); |
}; |
@@ -736,7 +731,10 @@ |
// CustomHistogram is a histogram for a set of custom integers. |
class BASE_EXPORT CustomHistogram : public Histogram { |
public: |
- |
+ // |custom_ranges| contains a vector of limits on ranges. Each limit should be |
+ // > 0 and < kSampleType_MAX. (Currently 0 is still accepted for backward |
+ // compatibility). The limits can be unordered or contain duplication, but |
+ // client should not depend on this. |
static Histogram* FactoryGet(const std::string& name, |
const std::vector<Sample>& custom_ranges, |
Flags flags); |
@@ -749,25 +747,27 @@ |
// This function ensures that a guard bucket exists right after any |
// valid sample value (unless the next higher sample is also a valid value), |
// so that invalid samples never fall into the same bucket as valid samples. |
+ // TODO(kaiwang): Change name to ArrayToCustomEnumRanges. |
static std::vector<Sample> ArrayToCustomRanges(const Sample* values, |
size_t num_values); |
// Helper for deserializing CustomHistograms. |*ranges| should already be |
// correctly sized before this call. Return true on success. |
static bool DeserializeRanges(PickleIterator* iter, |
- std::vector<Histogram::Sample>* ranges); |
- |
- |
+ std::vector<Sample>* ranges); |
protected: |
CustomHistogram(const std::string& name, |
- const std::vector<Sample>& custom_ranges); |
+ const BucketRanges* ranges); |
virtual bool SerializeRanges(Pickle* pickle) const OVERRIDE; |
- // Initialize ranges_ mapping in bucket_ranges_. |
- void InitializedCustomBucketRange(const std::vector<Sample>& custom_ranges); |
virtual double GetBucketSize(Count current, size_t i) const OVERRIDE; |
+ private: |
+ static bool ValidateCustomRanges(const std::vector<Sample>& custom_ranges); |
+ static BucketRanges* CreateBucketRangesFromCustomRanges( |
+ const std::vector<Sample>& custom_ranges); |
+ |
DISALLOW_COPY_AND_ASSIGN(CustomHistogram); |
}; |