| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Histogram is an object that aggregates statistics, and can summarize them in | 5 // Histogram is an object that aggregates statistics, and can summarize them in |
| 6 // various forms, including ASCII graphical, HTML, and numerically (as a | 6 // various forms, including ASCII graphical, HTML, and numerically (as a |
| 7 // vector of numbers corresponding to each of the aggregating buckets). | 7 // vector of numbers corresponding to each of the aggregating buckets). |
| 8 // See header file for details and examples. | 8 // See header file for details and examples. |
| 9 | 9 |
| 10 #include "base/histogram.h" | 10 #include "base/histogram.h" |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 WriteAsciiBucketContext(past, current, remaining, i, output); | 173 WriteAsciiBucketContext(past, current, remaining, i, output); |
| 174 output->append(newline); | 174 output->append(newline); |
| 175 past += current; | 175 past += current; |
| 176 } | 176 } |
| 177 DCHECK(past == sample_count); | 177 DCHECK(past == sample_count); |
| 178 } | 178 } |
| 179 | 179 |
| 180 bool Histogram::ValidateBucketRanges() const { | 180 bool Histogram::ValidateBucketRanges() const { |
| 181 // Standard assertions that all bucket ranges should satisfy. | 181 // Standard assertions that all bucket ranges should satisfy. |
| 182 DCHECK(ranges_.size() == bucket_count_ + 1); | 182 DCHECK(ranges_.size() == bucket_count_ + 1); |
| 183 DCHECK_EQ(0, ranges_[0]); | 183 DCHECK_EQ(ranges_[0], 0); |
| 184 DCHECK(declared_min() == ranges_[1]); | 184 DCHECK(declared_min() == ranges_[1]); |
| 185 DCHECK(declared_max() == ranges_[bucket_count_ - 1]); | 185 DCHECK(declared_max() == ranges_[bucket_count_ - 1]); |
| 186 DCHECK(kSampleType_MAX == ranges_[bucket_count_]); | 186 DCHECK(kSampleType_MAX == ranges_[bucket_count_]); |
| 187 return true; | 187 return true; |
| 188 } | 188 } |
| 189 | 189 |
| 190 void Histogram::Initialize() { | 190 void Histogram::Initialize() { |
| 191 sample_.Resize(*this); | 191 sample_.Resize(*this); |
| 192 if (declared_min_ <= 0) | 192 if (declared_min_ <= 0) |
| 193 declared_min_ = 1; | 193 declared_min_ = 1; |
| 194 if (declared_max_ >= kSampleType_MAX) | 194 if (declared_max_ >= kSampleType_MAX) |
| 195 declared_max_ = kSampleType_MAX - 1; | 195 declared_max_ = kSampleType_MAX - 1; |
| 196 DCHECK(declared_min_ <= declared_max_); | 196 DCHECK(declared_min_ <= declared_max_); |
| 197 DCHECK_LT(1u, bucket_count_); | 197 DCHECK_GT(bucket_count_, 1u); |
| 198 size_t maximal_bucket_count = declared_max_ - declared_min_ + 2; | 198 size_t maximal_bucket_count = declared_max_ - declared_min_ + 2; |
| 199 DCHECK(bucket_count_ <= maximal_bucket_count); | 199 DCHECK(bucket_count_ <= maximal_bucket_count); |
| 200 DCHECK_EQ(0, ranges_[0]); | 200 DCHECK_EQ(ranges_[0], 0); |
| 201 ranges_[bucket_count_] = kSampleType_MAX; | 201 ranges_[bucket_count_] = kSampleType_MAX; |
| 202 InitializeBucketRange(); | 202 InitializeBucketRange(); |
| 203 DCHECK(ValidateBucketRanges()); | 203 DCHECK(ValidateBucketRanges()); |
| 204 StatisticsRecorder::Register(this); | 204 StatisticsRecorder::Register(this); |
| 205 } | 205 } |
| 206 | 206 |
| 207 // Calculate what range of values are held in each bucket. | 207 // Calculate what range of values are held in each bucket. |
| 208 // We have to be careful that we don't pick a ratio between starting points in | 208 // We have to be careful that we don't pick a ratio between starting points in |
| 209 // consecutive buckets that is sooo small, that the integer bounds are the same | 209 // consecutive buckets that is sooo small, that the integer bounds are the same |
| 210 // (effectively making one bucket get no values). We need to avoid: | 210 // (effectively making one bucket get no values). We need to avoid: |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 } | 318 } |
| 319 | 319 |
| 320 void Histogram::WriteAsciiHeader(const SampleSet& snapshot, | 320 void Histogram::WriteAsciiHeader(const SampleSet& snapshot, |
| 321 Count sample_count, | 321 Count sample_count, |
| 322 std::string* output) const { | 322 std::string* output) const { |
| 323 StringAppendF(output, | 323 StringAppendF(output, |
| 324 "Histogram: %s recorded %d samples", | 324 "Histogram: %s recorded %d samples", |
| 325 histogram_name().c_str(), | 325 histogram_name().c_str(), |
| 326 sample_count); | 326 sample_count); |
| 327 if (0 == sample_count) { | 327 if (0 == sample_count) { |
| 328 DCHECK_EQ(0, snapshot.sum()); | 328 DCHECK_EQ(snapshot.sum(), 0); |
| 329 } else { | 329 } else { |
| 330 double average = static_cast<float>(snapshot.sum()) / sample_count; | 330 double average = static_cast<float>(snapshot.sum()) / sample_count; |
| 331 double variance = static_cast<float>(snapshot.square_sum())/sample_count | 331 double variance = static_cast<float>(snapshot.square_sum())/sample_count |
| 332 - average * average; | 332 - average * average; |
| 333 double standard_deviation = sqrt(variance); | 333 double standard_deviation = sqrt(variance); |
| 334 | 334 |
| 335 StringAppendF(output, | 335 StringAppendF(output, |
| 336 ", average = %.1f, standard deviation = %.1f", | 336 ", average = %.1f, standard deviation = %.1f", |
| 337 average, standard_deviation); | 337 average, standard_deviation); |
| 338 } | 338 } |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 639 return Histogram::GetAsciiBucketRange(i); | 639 return Histogram::GetAsciiBucketRange(i); |
| 640 return it->second; | 640 return it->second; |
| 641 } | 641 } |
| 642 | 642 |
| 643 bool LinearHistogram::PrintEmptyBucket(size_t index) const { | 643 bool LinearHistogram::PrintEmptyBucket(size_t index) const { |
| 644 return bucket_description_.find(ranges(index)) == bucket_description_.end(); | 644 return bucket_description_.find(ranges(index)) == bucket_description_.end(); |
| 645 } | 645 } |
| 646 | 646 |
| 647 | 647 |
| 648 void LinearHistogram::InitializeBucketRange() { | 648 void LinearHistogram::InitializeBucketRange() { |
| 649 DCHECK_LT(0, declared_min()); // 0 is the underflow bucket here. | 649 DCHECK_GT(declared_min(), 0); // 0 is the underflow bucket here. |
| 650 double min = declared_min(); | 650 double min = declared_min(); |
| 651 double max = declared_max(); | 651 double max = declared_max(); |
| 652 size_t i; | 652 size_t i; |
| 653 for (i = 1; i < bucket_count(); ++i) { | 653 for (i = 1; i < bucket_count(); ++i) { |
| 654 double linear_range = (min * (bucket_count() -1 - i) + max * (i - 1)) / | 654 double linear_range = (min * (bucket_count() -1 - i) + max * (i - 1)) / |
| 655 (bucket_count() - 2); | 655 (bucket_count() - 2); |
| 656 SetBucketRange(i, static_cast<int> (linear_range + 0.5)); | 656 SetBucketRange(i, static_cast<int> (linear_range + 0.5)); |
| 657 } | 657 } |
| 658 } | 658 } |
| 659 | 659 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 684 histogram = registered_histogram; | 684 histogram = registered_histogram; |
| 685 } | 685 } |
| 686 | 686 |
| 687 DCHECK(BOOLEAN_HISTOGRAM == histogram->histogram_type()); | 687 DCHECK(BOOLEAN_HISTOGRAM == histogram->histogram_type()); |
| 688 histogram->SetFlags(flags); | 688 histogram->SetFlags(flags); |
| 689 return histogram; | 689 return histogram; |
| 690 } | 690 } |
| 691 | 691 |
| 692 | 692 |
| 693 //------------------------------------------------------------------------------ | 693 //------------------------------------------------------------------------------ |
| 694 // CustomHistogram: |
| 695 //------------------------------------------------------------------------------ |
| 696 |
| 697 scoped_refptr<Histogram> CustomHistogram::FactoryGet( |
| 698 const std::string& name, const std::vector<int>& custom_ranges, |
| 699 Flags flags) { |
| 700 scoped_refptr<Histogram> histogram(NULL); |
| 701 |
| 702 // Remove the duplicates in the custom ranges array. |
| 703 std::vector<int> ranges = custom_ranges; |
| 704 ranges.push_back(0); // Ensure we have a zero value. |
| 705 std::sort(ranges.begin(), ranges.end()); |
| 706 ranges.erase(std::unique(ranges.begin(), ranges.end()), ranges.end()); |
| 707 if (ranges.size() <= 1) { |
| 708 DCHECK(false); |
| 709 // Note that we pushed a 0 in above, so for defensive code.... |
| 710 ranges.push_back(1); // Put in some data so we can index to [1]. |
| 711 } |
| 712 |
| 713 DCHECK_LT(ranges.back(), kSampleType_MAX); |
| 714 |
| 715 if (StatisticsRecorder::FindHistogram(name, &histogram)) { |
| 716 DCHECK(histogram.get()); |
| 717 DCHECK_EQ(histogram->histogram_type(), CUSTOM_HISTOGRAM); |
| 718 } else { |
| 719 histogram = new CustomHistogram(name, ranges); |
| 720 scoped_refptr<Histogram> registered_histogram(NULL); |
| 721 StatisticsRecorder::FindHistogram(name, ®istered_histogram); |
| 722 if (registered_histogram.get() && |
| 723 registered_histogram.get() != histogram.get()) |
| 724 histogram = registered_histogram; |
| 725 } |
| 726 |
| 727 DCHECK_EQ(histogram->histogram_type(), CUSTOM_HISTOGRAM); |
| 728 DCHECK(histogram->HasConstructorArguments(ranges[1], ranges.back(), |
| 729 ranges.size())); |
| 730 histogram->SetFlags(flags); |
| 731 return histogram; |
| 732 } |
| 733 |
| 734 CustomHistogram::CustomHistogram(const std::string& name, |
| 735 const std::vector<int>& custom_ranges) |
| 736 : Histogram(name, custom_ranges[1], custom_ranges.back(), |
| 737 custom_ranges.size()) { |
| 738 DCHECK_GT(custom_ranges.size(), 1u); |
| 739 DCHECK_EQ(custom_ranges[0], 0); |
| 740 ranges_vector_ = &custom_ranges; |
| 741 InitializeBucketRange(); |
| 742 ranges_vector_ = NULL; |
| 743 DCHECK(ValidateBucketRanges()); |
| 744 } |
| 745 |
| 746 void CustomHistogram::InitializeBucketRange() { |
| 747 DCHECK(ranges_vector_->size() <= bucket_count()); |
| 748 for (size_t index = 0; index < ranges_vector_->size(); ++index) { |
| 749 SetBucketRange(index, (*ranges_vector_)[index]); |
| 750 } |
| 751 } |
| 752 |
| 753 double CustomHistogram::GetBucketSize(Count current, size_t i) const { |
| 754 return 1; |
| 755 } |
| 756 |
| 757 //------------------------------------------------------------------------------ |
| 694 // The next section handles global (central) support for all histograms, as well | 758 // The next section handles global (central) support for all histograms, as well |
| 695 // as startup/teardown of this service. | 759 // as startup/teardown of this service. |
| 696 //------------------------------------------------------------------------------ | 760 //------------------------------------------------------------------------------ |
| 697 | 761 |
| 698 // This singleton instance should be started during the single threaded portion | 762 // This singleton instance should be started during the single threaded portion |
| 699 // of main(), and hence it is not thread safe. It initializes globals to | 763 // of main(), and hence it is not thread safe. It initializes globals to |
| 700 // provide support for all future calls. | 764 // provide support for all future calls. |
| 701 StatisticsRecorder::StatisticsRecorder() { | 765 StatisticsRecorder::StatisticsRecorder() { |
| 702 DCHECK(!histograms_); | 766 DCHECK(!histograms_); |
| 703 lock_ = new Lock; | 767 lock_ = new Lock; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 822 snapshot->push_back(it->second); | 886 snapshot->push_back(it->second); |
| 823 } | 887 } |
| 824 } | 888 } |
| 825 | 889 |
| 826 // static | 890 // static |
| 827 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; | 891 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; |
| 828 // static | 892 // static |
| 829 Lock* StatisticsRecorder::lock_ = NULL; | 893 Lock* StatisticsRecorder::lock_ = NULL; |
| 830 // static | 894 // static |
| 831 bool StatisticsRecorder::dump_on_exit_ = false; | 895 bool StatisticsRecorder::dump_on_exit_ = false; |
| OLD | NEW |