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

Unified Diff: base/metrics/histogram.cc

Issue 10829466: SampleSet -> HistogramSamples (will be reused by SparseHistogram) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 3 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
« no previous file with comments | « base/metrics/histogram.h ('k') | base/metrics/histogram_flattener.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/metrics/histogram.cc
===================================================================
--- base/metrics/histogram.cc (revision 155400)
+++ base/metrics/histogram.cc (working copy)
@@ -34,104 +34,6 @@
// static
const size_t Histogram::kBucketCount_MAX = 16384u;
-Histogram::SampleSet::SampleSet(size_t size)
- : counts_(size, 0),
- sum_(0),
- redundant_count_(0) {}
-
-Histogram::SampleSet::SampleSet()
- : counts_(),
- sum_(0),
- redundant_count_(0) {}
-
-Histogram::SampleSet::~SampleSet() {}
-
-void Histogram::SampleSet::Resize(size_t size) {
- counts_.resize(size, 0);
-}
-
-void Histogram::SampleSet::Accumulate(Sample value, Count count,
- size_t index) {
- DCHECK(count == 1 || count == -1);
- counts_[index] += count;
- sum_ += count * value;
- redundant_count_ += count;
- DCHECK_GE(counts_[index], 0);
- DCHECK_GE(sum_, 0);
- DCHECK_GE(redundant_count_, 0);
-}
-
-Count Histogram::SampleSet::TotalCount() const {
- Count total = 0;
- for (Counts::const_iterator it = counts_.begin();
- it != counts_.end();
- ++it) {
- total += *it;
- }
- return total;
-}
-
-void Histogram::SampleSet::Add(const SampleSet& other) {
- DCHECK_EQ(counts_.size(), other.counts_.size());
- sum_ += other.sum_;
- redundant_count_ += other.redundant_count_;
- for (size_t index = 0; index < counts_.size(); ++index)
- counts_[index] += other.counts_[index];
-}
-
-void Histogram::SampleSet::Subtract(const SampleSet& other) {
- DCHECK_EQ(counts_.size(), other.counts_.size());
- // Note: Race conditions in snapshotting a sum may lead to (temporary)
- // negative values when snapshots are later combined (and deltas calculated).
- // As a result, we don't currently CHCEK() for positive values.
- sum_ -= other.sum_;
- redundant_count_ -= other.redundant_count_;
- for (size_t index = 0; index < counts_.size(); ++index) {
- counts_[index] -= other.counts_[index];
- DCHECK_GE(counts_[index], 0);
- }
-}
-
-bool Histogram::SampleSet::Serialize(Pickle* pickle) const {
- pickle->WriteInt64(sum_);
- pickle->WriteInt64(redundant_count_);
- pickle->WriteUInt64(counts_.size());
-
- for (size_t index = 0; index < counts_.size(); ++index) {
- pickle->WriteInt(counts_[index]);
- }
-
- return true;
-}
-
-bool Histogram::SampleSet::Deserialize(PickleIterator* iter) {
- DCHECK_EQ(counts_.size(), 0u);
- DCHECK_EQ(sum_, 0);
- DCHECK_EQ(redundant_count_, 0);
-
- uint64 counts_size;
-
- if (!iter->ReadInt64(&sum_) ||
- !iter->ReadInt64(&redundant_count_) ||
- !iter->ReadUInt64(&counts_size)) {
- return false;
- }
-
- if (counts_size == 0)
- return false;
-
- int count = 0;
- for (uint64 index = 0; index < counts_size; ++index) {
- int i;
- if (!iter->ReadInt(&i))
- return false;
- counts_.push_back(i);
- count += i;
- }
- DCHECK_EQ(count, redundant_count_);
- return count == redundant_count_;
-}
-
// TODO(rtenneti): delete this code after debugging.
void CheckCorruption(const Histogram& histogram, bool new_histogram) {
const std::string& histogram_name = histogram.histogram_name();
@@ -245,26 +147,29 @@
ranges->ResetChecksum();
}
-// static
void Histogram::Add(int value) {
+ DCHECK_EQ(0, ranges(0));
+ DCHECK_EQ(kSampleType_MAX, ranges(bucket_count_));
+
if (value > kSampleType_MAX - 1)
value = kSampleType_MAX - 1;
if (value < 0)
value = 0;
- size_t index = BucketIndex(value);
- DCHECK_GE(value, ranges(index));
- DCHECK_LT(value, ranges(index + 1));
- Accumulate(value, 1, index);
+ samples_->Accumulate(value, 1);
}
void Histogram::AddBoolean(bool value) {
DCHECK(false);
}
-void Histogram::AddSampleSet(const SampleSet& sample) {
- sample_.Add(sample);
+void Histogram::AddSamples(const HistogramSamples& samples) {
+ samples_->Add(samples);
}
+bool Histogram::AddSamplesFromPickle(PickleIterator* iter) {
+ return samples_->AddFromPickle(iter);
+}
+
void Histogram::SetRangeDescriptions(const DescriptionPair descriptions[]) {
DCHECK(false);
}
@@ -283,7 +188,7 @@
// static
string Histogram::SerializeHistogramInfo(const Histogram& histogram,
- const SampleSet& snapshot) {
+ const HistogramSamples& snapshot) {
DCHECK_NE(NOT_VALID_IN_RENDERER, histogram.histogram_type());
DCHECK(histogram.bucket_ranges()->HasValidChecksum());
@@ -296,10 +201,10 @@
pickle.WriteInt(histogram.histogram_type());
pickle.WriteInt(histogram.flags());
- snapshot.Serialize(&pickle);
-
histogram.SerializeRanges(&pickle);
+ snapshot.Serialize(&pickle);
+
return string(static_cast<const char*>(pickle.data()), pickle.size());
}
@@ -318,7 +223,6 @@
uint32 range_checksum;
int histogram_type;
int pickle_flags;
- SampleSet sample;
PickleIterator iter(pickle);
if (!iter.ReadString(&histogram_name) ||
@@ -327,8 +231,7 @@
!iter.ReadUInt64(&bucket_count) ||
!iter.ReadUInt32(&range_checksum) ||
!iter.ReadInt(&histogram_type) ||
- !iter.ReadInt(&pickle_flags) ||
- !sample.Histogram::SampleSet::Deserialize(&iter)) {
+ !iter.ReadInt(&pickle_flags)) {
DLOG(ERROR) << "Pickle error decoding Histogram: " << histogram_name;
return false;
}
@@ -382,23 +285,21 @@
if (render_histogram->flags() & kIPCSerializationSourceFlag) {
DVLOG(1) << "Single process mode, histogram observed and not copied: "
<< histogram_name;
- } else {
- DCHECK_EQ(flags & render_histogram->flags(), flags);
- render_histogram->AddSampleSet(sample);
+ return true;
}
- return true;
+ DCHECK_EQ(flags & render_histogram->flags(), flags);
+ return render_histogram->AddSamplesFromPickle(&iter);
}
+// static
+const int Histogram::kCommonRaceBasedCountMismatch = 5;
-// Validate a sample and related histogram.
Histogram::Inconsistencies Histogram::FindCorruption(
- const SampleSet& snapshot) const {
+ const HistogramSamples& samples) const {
int inconsistencies = NO_INCONSISTENCIES;
Sample previous_range = -1; // Bottom range is always 0.
- int64 count = 0;
for (size_t index = 0; index < bucket_count(); ++index) {
- count += snapshot.counts(index);
int new_range = ranges(index);
if (previous_range >= new_range)
inconsistencies |= BUCKET_ORDER_ERROR;
@@ -408,20 +309,11 @@
if (!bucket_ranges()->HasValidChecksum())
inconsistencies |= RANGE_CHECKSUM_ERROR;
- int64 delta64 = snapshot.redundant_count() - count;
+ int64 delta64 = samples.redundant_count() - samples.TotalCount();
if (delta64 != 0) {
int delta = static_cast<int>(delta64);
if (delta != delta64)
delta = INT_MAX; // Flag all giant errors as INT_MAX.
- // Since snapshots of histograms are taken asynchronously relative to
- // sampling (and snapped from different threads), it is pretty likely that
- // we'll catch a redundant count that doesn't match the sample count. We
- // allow for a certain amount of slop before flagging this as an
- // inconsistency. Even with an inconsistency, we'll snapshot it again (for
- // UMA in about a half hour, so we'll eventually get the data, if it was
- // not the result of a corruption. If histograms show that 1 is "too tight"
- // then we may try to use 2 or 3 for this slop value.
- const int kCommonRaceBasedCountMismatch = 5;
if (delta > 0) {
UMA_HISTOGRAM_COUNTS("Histogram.InconsistentCountHigh", delta);
if (delta > kCommonRaceBasedCountMismatch)
@@ -448,11 +340,10 @@
return bucket_count_;
}
-// Do a safe atomic snapshot of sample data.
-// This implementation assumes we are on a safe single thread.
-void Histogram::SnapshotSample(SampleSet* sample) const {
- // Note locking not done in this version!!!
- *sample = sample_;
+scoped_ptr<SampleVector> Histogram::SnapshotSamples() const {
+ scoped_ptr<SampleVector> samples(new SampleVector(bucket_ranges()));
+ samples->Add(*samples_);
+ return samples.Pass();
}
bool Histogram::HasConstructionArguments(Sample minimum,
@@ -471,8 +362,10 @@
bucket_ranges_(ranges),
declared_min_(minimum),
declared_max_(maximum),
- bucket_count_(bucket_count),
- sample_(bucket_count) {}
+ bucket_count_(bucket_count) {
+ if (ranges)
+ samples_.reset(new SampleVector(ranges));
+}
Histogram::~Histogram() {
if (StatisticsRecorder::dump_on_exit()) {
@@ -519,31 +412,6 @@
return true;
}
-size_t Histogram::BucketIndex(Sample value) const {
- // Use simple binary search. This is very general, but there are better
- // approaches if we knew that the buckets were linearly distributed.
- DCHECK_LE(ranges(0), value);
- DCHECK_GT(ranges(bucket_count()), value);
- size_t under = 0;
- size_t over = bucket_count();
- size_t mid;
-
- do {
- DCHECK_GE(over, under);
- mid = under + (over - under)/2;
- if (mid == under)
- break;
- if (ranges(mid) <= value)
- under = mid;
- else
- over = mid;
- } while (true);
-
- DCHECK_LE(ranges(mid), value);
- CHECK_GT(ranges(mid+1), value);
- return mid;
-}
-
// Use the actual bucket widths (like a linear histogram) until the widths get
// over some transition value, and then use that transition width. Exponentials
// get so big so fast (and we don't expect to see a lot of entries in the large
@@ -567,12 +435,6 @@
return result;
}
-// Update histogram data with new sample.
-void Histogram::Accumulate(Sample value, Count count, size_t index) {
- // Note locking not done in this version!!!
- sample_.Accumulate(value, count, index);
-}
-
//------------------------------------------------------------------------------
// Private methods
@@ -581,22 +443,21 @@
string* output) const {
// Get local (stack) copies of all effectively volatile class data so that we
// are consistent across our output activities.
- SampleSet snapshot;
- SnapshotSample(&snapshot);
- Count sample_count = snapshot.TotalCount();
+ scoped_ptr<SampleVector> snapshot = SnapshotSamples();
+ Count sample_count = snapshot->TotalCount();
- WriteAsciiHeader(snapshot, sample_count, output);
+ WriteAsciiHeader(*snapshot, sample_count, output);
output->append(newline);
// Prepare to normalize graphical rendering of bucket contents.
double max_size = 0;
if (graph_it)
- max_size = GetPeakBucketSize(snapshot);
+ max_size = GetPeakBucketSize(*snapshot);
// Calculate space needed to print bucket range numbers. Leave room to print
// nearly the largest bucket range without sliding over the histogram.
size_t largest_non_empty_bucket = bucket_count() - 1;
- while (0 == snapshot.counts(largest_non_empty_bucket)) {
+ while (0 == snapshot->GetCountAtIndex(largest_non_empty_bucket)) {
if (0 == largest_non_empty_bucket)
break; // All buckets are empty.
--largest_non_empty_bucket;
@@ -605,7 +466,7 @@
// Calculate largest print width needed for any of our bucket range displays.
size_t print_width = 1;
for (size_t i = 0; i < bucket_count(); ++i) {
- if (snapshot.counts(i)) {
+ if (snapshot->GetCountAtIndex(i)) {
size_t width = GetAsciiBucketRange(i).size() + 1;
if (width > print_width)
print_width = width;
@@ -616,7 +477,7 @@
int64 past = 0;
// Output the actual histogram graph.
for (size_t i = 0; i < bucket_count(); ++i) {
- Count current = snapshot.counts(i);
+ Count current = snapshot->GetCountAtIndex(i);
if (!current && !PrintEmptyBucket(i))
continue;
remaining -= current;
@@ -624,9 +485,12 @@
output->append(range);
for (size_t j = 0; range.size() + j < print_width + 1; ++j)
output->push_back(' ');
- if (0 == current && i < bucket_count() - 1 && 0 == snapshot.counts(i + 1)) {
- while (i < bucket_count() - 1 && 0 == snapshot.counts(i + 1))
+ if (0 == current && i < bucket_count() - 1 &&
+ 0 == snapshot->GetCountAtIndex(i + 1)) {
+ while (i < bucket_count() - 1 &&
+ 0 == snapshot->GetCountAtIndex(i + 1)) {
++i;
+ }
output->append("... ");
output->append(newline);
continue; // No reason to plot emptiness.
@@ -641,17 +505,17 @@
DCHECK_EQ(sample_count, past);
}
-double Histogram::GetPeakBucketSize(const SampleSet& snapshot) const {
+double Histogram::GetPeakBucketSize(const SampleVector& samples) const {
double max = 0;
for (size_t i = 0; i < bucket_count() ; ++i) {
- double current_size = GetBucketSize(snapshot.counts(i), i);
+ double current_size = GetBucketSize(samples.GetCountAtIndex(i), i);
if (current_size > max)
max = current_size;
}
return max;
}
-void Histogram::WriteAsciiHeader(const SampleSet& snapshot,
+void Histogram::WriteAsciiHeader(const SampleVector& samples,
Count sample_count,
string* output) const {
StringAppendF(output,
@@ -659,9 +523,9 @@
histogram_name().c_str(),
sample_count);
if (0 == sample_count) {
- DCHECK_EQ(snapshot.sum(), 0);
+ DCHECK_EQ(samples.sum(), 0);
} else {
- double average = static_cast<float>(snapshot.sum()) / sample_count;
+ double average = static_cast<float>(samples.sum()) / sample_count;
StringAppendF(output, ", average = %.1f", average);
}
« no previous file with comments | « base/metrics/histogram.h ('k') | base/metrics/histogram_flattener.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698