| Index: base/metrics/sample_vector.cc
|
| ===================================================================
|
| --- base/metrics/sample_vector.cc (revision 0)
|
| +++ base/metrics/sample_vector.cc (revision 0)
|
| @@ -0,0 +1,160 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/metrics/sample_vector.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/metrics/bucket_ranges.h"
|
| +
|
| +using std::vector;
|
| +
|
| +namespace base {
|
| +
|
| +typedef HistogramBase::Count Count;
|
| +typedef HistogramBase::Sample Sample;
|
| +
|
| +SampleVector::SampleVector(const BucketRanges* bucket_ranges)
|
| + : counts_(bucket_ranges->size() - 1),
|
| + bucket_ranges_(bucket_ranges) {
|
| + CHECK_GE(bucket_ranges_->size(), 2u);
|
| +}
|
| +
|
| +SampleVector::~SampleVector() {}
|
| +
|
| +void SampleVector::Accumulate(Sample value, Count count) {
|
| + size_t bucket_index = GetBucketIndex(value);
|
| + counts_[bucket_index] += count;
|
| + IncreaseSum(count * value);
|
| + IncreaseRedundantCount(count);
|
| +}
|
| +
|
| +Count SampleVector::GetCount(Sample value) const {
|
| + size_t bucket_index = GetBucketIndex(value);
|
| + return counts_[bucket_index];
|
| +}
|
| +
|
| +Count SampleVector::TotalCount() const {
|
| + Count count = 0;
|
| + for (size_t i = 0; i < counts_.size(); i++) {
|
| + count += counts_[i];
|
| + }
|
| + return count;
|
| +}
|
| +
|
| +Count SampleVector::GetCountAtIndex(size_t bucket_index) const {
|
| + DCHECK(bucket_index >= 0 && bucket_index < counts_.size());
|
| + return counts_[bucket_index];
|
| +}
|
| +
|
| +scoped_ptr<SampleCountIterator> SampleVector::Iterator() const {
|
| + return scoped_ptr<SampleCountIterator>(
|
| + new SampleVectorIterator(&counts_, bucket_ranges_));
|
| +}
|
| +
|
| +bool SampleVector::AddSubtractImpl(SampleCountIterator* iter,
|
| + HistogramSamples::Instruction instruction) {
|
| + HistogramBase::Sample min;
|
| + HistogramBase::Sample max;
|
| + HistogramBase::Count count;
|
| +
|
| + // Go through the iterator and add the counts into correct bucket.
|
| + size_t index = 0;
|
| + while (index < counts_.size() && !iter->Done()) {
|
| + iter->Get(&min, &max, &count);
|
| + if (min == bucket_ranges_->range(index) &&
|
| + max == bucket_ranges_->range(index + 1)) {
|
| + // Sample matches this bucket!
|
| + counts_[index] +=
|
| + (instruction == HistogramSamples::ADD) ? count : -count;
|
| + iter->Next();
|
| + } else if (min > bucket_ranges_->range(index)) {
|
| + // Sample is larger than current bucket range. Try next.
|
| + index++;
|
| + } else {
|
| + // Sample is smaller than current bucket range. We scan buckets from
|
| + // smallest to largest, so the sample value must be invalid.
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + return iter->Done();
|
| +}
|
| +
|
| +// Use simple binary search. This is very general, but there are better
|
| +// approaches if we knew that the buckets were linearly distributed.
|
| +size_t SampleVector::GetBucketIndex(Sample value) const {
|
| + size_t bucket_count = bucket_ranges_->size() - 1;
|
| + CHECK_GE(bucket_count, 1u);
|
| + CHECK_GE(value, bucket_ranges_->range(0));
|
| + CHECK_LT(value, bucket_ranges_->range(bucket_count));
|
| +
|
| + 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 (bucket_ranges_->range(mid) <= value)
|
| + under = mid;
|
| + else
|
| + over = mid;
|
| + } while (true);
|
| +
|
| + DCHECK_LE(bucket_ranges_->range(mid), value);
|
| + CHECK_GT(bucket_ranges_->range(mid + 1), value);
|
| + return mid;
|
| +}
|
| +
|
| +SampleVectorIterator::SampleVectorIterator(const vector<Count>* counts,
|
| + const BucketRanges* bucket_ranges)
|
| + : counts_(counts),
|
| + bucket_ranges_(bucket_ranges),
|
| + index_(0) {
|
| + CHECK_GT(bucket_ranges_->size(), counts_->size());
|
| + SkipEmptyBuckets();
|
| +}
|
| +
|
| +bool SampleVectorIterator::Done() const {
|
| + return index_ >= counts_->size();
|
| +}
|
| +
|
| +void SampleVectorIterator::Next() {
|
| + DCHECK(!Done());
|
| + index_++;
|
| + SkipEmptyBuckets();
|
| +}
|
| +
|
| +void SampleVectorIterator::Get(HistogramBase::Sample* min,
|
| + HistogramBase::Sample* max,
|
| + HistogramBase::Count* count) const {
|
| + DCHECK(!Done());
|
| + if (min != NULL)
|
| + *min = bucket_ranges_->range(index_);
|
| + if (max != NULL)
|
| + *max = bucket_ranges_->range(index_ + 1);
|
| + if (count != NULL)
|
| + *count = (*counts_)[index_];
|
| +}
|
| +
|
| +bool SampleVectorIterator::GetBucketIndex(size_t* index) const {
|
| + DCHECK(!Done());
|
| + if (index != NULL)
|
| + *index = index_;
|
| + return true;
|
| +}
|
| +
|
| +void SampleVectorIterator::SkipEmptyBuckets() {
|
| + if (Done())
|
| + return;
|
| +
|
| + while (index_ < counts_->size()) {
|
| + if ((*counts_)[index_] != 0)
|
| + return;
|
| + index_++;
|
| + }
|
| +}
|
| +
|
| +} // namespace base
|
|
|
| Property changes on: base/metrics/sample_vector.cc
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|