Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(778)

Unified Diff: base/metrics/histogram.h

Issue 10834011: Refactor of Histogram related code (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
};

Powered by Google App Engine
This is Rietveld 408576698