summaryrefslogtreecommitdiffstats
path: root/base/metrics/histogram.h
diff options
context:
space:
mode:
Diffstat (limited to 'base/metrics/histogram.h')
-rw-r--r--base/metrics/histogram.h61
1 files changed, 56 insertions, 5 deletions
diff --git a/base/metrics/histogram.h b/base/metrics/histogram.h
index 20f67c2..000807a 100644
--- a/base/metrics/histogram.h
+++ b/base/metrics/histogram.h
@@ -36,6 +36,7 @@
#include <string>
#include <vector>
+#include "base/gtest_prod_util.h"
#include "base/ref_counted.h"
#include "base/logging.h"
#include "base/time.h"
@@ -243,8 +244,8 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> {
typedef std::vector<Count> Counts;
typedef std::vector<Sample> Ranges;
- /* These enums are meant to facilitate deserialization of renderer histograms
- into the browser. */
+ // These enums are used to facilitate deserialization of renderer histograms
+ // into the browser.
enum ClassType {
HISTOGRAM,
LINEAR_HISTOGRAM,
@@ -273,6 +274,16 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> {
kHexRangePrintingFlag = 0x8000, // Fancy bucket-naming supported.
};
+ enum Inconsistencies {
+ NO_INCONSISTENCIES = 0x0,
+ RANGE_CHECKSUM_ERROR = 0x1,
+ BUCKET_ORDER_ERROR = 0x2,
+ COUNT_HIGH_ERROR = 0x4,
+ COUNT_LOW_ERROR = 0x8,
+
+ NEVER_EXCEEDED_VALUE = 0x10
+ };
+
struct DescriptionPair {
Sample sample;
const char* description; // Null means end of a list of pairs.
@@ -298,6 +309,7 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> {
Count TotalCount() const;
int64 sum() const { return sum_; }
int64 square_sum() const { return square_sum_; }
+ int64 redundant_count() const { return redundant_count_; }
// Arithmetic manipulation of corresponding elements of the set.
void Add(const SampleSet& other);
@@ -315,7 +327,21 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> {
// without shared memory at some point.
int64 sum_; // sum of samples.
int64 square_sum_; // sum of squares of samples.
+
+ private:
+ // Allow tests to corrupt our innards for testing purposes.
+ FRIEND_TEST(HistogramTest, CorruptSampleCounts);
+
+ // To help identify memory corruption, we reduntantly save the number of
+ // samples we've accumulated into all of our buckets. We can compare this
+ // count to the sum of the counts in all buckets, and detect problems. Note
+ // that due to races in histogram accumulation (if a histogram is indeed
+ // updated on several threads simultaneously), the tallies might mismatch,
+ // and also the snapshotting code may asynchronously get a mismatch (though
+ // generally either race based mismatch cause is VERY rare).
+ int64 redundant_count_;
};
+
//----------------------------------------------------------------------------
// minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit
// default underflow bucket.
@@ -367,6 +393,13 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> {
// browser process.
static bool DeserializeHistogramInfo(const std::string& histogram_info);
+ // Check to see if bucket ranges, counts and tallies in the snapshot are
+ // consistent with the bucket ranges and checksums in our histogram. This can
+ // produce a false-alarm if a race occurred in the reading of the data during
+ // a SnapShot process, but should otherwise be false at all times (unless we
+ // have memory over-writes, or DRAM failures).
+ Inconsistencies FindCorruption(const SampleSet& snapshot) const;
+
//----------------------------------------------------------------------------
// Accessors for factory constuction, serialization and testing.
//----------------------------------------------------------------------------
@@ -375,6 +408,7 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> {
Sample declared_min() const { return declared_min_; }
Sample declared_max() const { return declared_max_; }
virtual Sample ranges(size_t i) const { return ranges_[i];}
+ Sample range_checksum() const { return range_checksum_; }
virtual size_t bucket_count() const { return bucket_count_; }
// Snapshot the current complete set of sample data.
// Override with atomic/locked snapshot if needed.
@@ -409,6 +443,9 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> {
// 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.
@@ -430,9 +467,18 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> {
bool ValidateBucketRanges() const;
private:
+ // Allow tests to corrupt our innards for testing purposes.
+ FRIEND_TEST(HistogramTest, CorruptBucketBounds);
+ FRIEND_TEST(HistogramTest, CorruptSampleCounts);
+
// Post constructor initialization.
void Initialize();
+ // Return true iff the range_checksum_ matches current ranges_ vector.
+ bool HasValidRangeChecksum() const;
+
+ Sample CalculateRangeChecksum() const;
+
//----------------------------------------------------------------------------
// Helpers for emitting Ascii graphic. Each method appends data to output.
@@ -477,6 +523,11 @@ class Histogram : public base::RefCountedThreadSafe<Histogram> {
// The dimension of ranges_ is bucket_count + 1.
Ranges ranges_;
+ // For redundancy, we store the sum of all the sample ranges when ranges are
+ // generated. If ever there is ever a difference, then the histogram must
+ // have been corrupted.
+ Sample range_checksum_;
+
// Finally, provide the state that changes with the addition of each new
// sample.
SampleSet sample_;
@@ -561,11 +612,11 @@ class CustomHistogram : public Histogram {
virtual ClassType histogram_type() const;
static scoped_refptr<Histogram> FactoryGet(const std::string& name,
- const std::vector<int>& custom_ranges, Flags flags);
+ const std::vector<Sample>& custom_ranges, Flags flags);
protected:
CustomHistogram(const std::string& name,
- const std::vector<int>& custom_ranges);
+ const std::vector<Sample>& custom_ranges);
// Initialize ranges_ mapping.
virtual void InitializeBucketRange();
@@ -573,7 +624,7 @@ class CustomHistogram : public Histogram {
private:
// Temporary pointer used during construction/initialization, and then NULLed.
- const std::vector<int>* ranges_vector_;
+ const std::vector<Sample>* ranges_vector_;
DISALLOW_COPY_AND_ASSIGN(CustomHistogram);
};