OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 | 79 |
80 // Defensive code. | 80 // Defensive code. |
81 if (minimum < 1) | 81 if (minimum < 1) |
82 minimum = 1; | 82 minimum = 1; |
83 if (maximum > kSampleType_MAX - 1) | 83 if (maximum > kSampleType_MAX - 1) |
84 maximum = kSampleType_MAX - 1; | 84 maximum = kSampleType_MAX - 1; |
85 | 85 |
86 if (!StatisticsRecorder::FindHistogram(name, &histogram)) { | 86 if (!StatisticsRecorder::FindHistogram(name, &histogram)) { |
87 histogram = new Histogram(name, minimum, maximum, bucket_count); | 87 histogram = new Histogram(name, minimum, maximum, bucket_count); |
88 histogram->InitializeBucketRange(); | 88 histogram->InitializeBucketRange(); |
89 StatisticsRecorder::Register(&histogram); | 89 StatisticsRecorder::RegisterOrDiscardDuplicate(&histogram); |
90 } | 90 } |
91 | 91 |
92 DCHECK_EQ(HISTOGRAM, histogram->histogram_type()); | 92 DCHECK_EQ(HISTOGRAM, histogram->histogram_type()); |
93 DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count)); | 93 DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count)); |
94 histogram->SetFlags(flags); | 94 histogram->SetFlags(flags); |
95 return histogram; | 95 return histogram; |
96 } | 96 } |
97 | 97 |
98 scoped_refptr<Histogram> Histogram::FactoryTimeGet(const std::string& name, | 98 scoped_refptr<Histogram> Histogram::FactoryTimeGet(const std::string& name, |
99 TimeDelta minimum, | 99 TimeDelta minimum, |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 if (StatisticsRecorder::dump_on_exit()) { | 408 if (StatisticsRecorder::dump_on_exit()) { |
409 std::string output; | 409 std::string output; |
410 WriteAscii(true, "\n", &output); | 410 WriteAscii(true, "\n", &output); |
411 LOG(INFO) << output; | 411 LOG(INFO) << output; |
412 } | 412 } |
413 | 413 |
414 // Just to make sure most derived class did this properly... | 414 // Just to make sure most derived class did this properly... |
415 DCHECK(ValidateBucketRanges()); | 415 DCHECK(ValidateBucketRanges()); |
416 } | 416 } |
417 | 417 |
418 bool Histogram::PrintEmptyBucket(size_t index) const { | |
419 return true; | |
420 } | |
421 | |
422 // Calculate what range of values are held in each bucket. | 418 // Calculate what range of values are held in each bucket. |
423 // We have to be careful that we don't pick a ratio between starting points in | 419 // We have to be careful that we don't pick a ratio between starting points in |
424 // consecutive buckets that is sooo small, that the integer bounds are the same | 420 // consecutive buckets that is sooo small, that the integer bounds are the same |
425 // (effectively making one bucket get no values). We need to avoid: | 421 // (effectively making one bucket get no values). We need to avoid: |
426 // ranges_[i] == ranges_[i + 1] | 422 // ranges_[i] == ranges_[i + 1] |
427 // To avoid that, we just do a fine-grained bucket width as far as we need to | 423 // To avoid that, we just do a fine-grained bucket width as far as we need to |
428 // until we get a ratio that moves us along at least 2 units at a time. From | 424 // until we get a ratio that moves us along at least 2 units at a time. From |
429 // that bucket onward we do use the exponential growth of buckets. | 425 // that bucket onward we do use the exponential growth of buckets. |
430 void Histogram::InitializeBucketRange() { | 426 void Histogram::InitializeBucketRange() { |
431 double log_max = log(static_cast<double>(declared_max())); | 427 double log_max = log(static_cast<double>(declared_max())); |
(...skipping 15 matching lines...) Expand all Loading... |
447 current = next; | 443 current = next; |
448 else | 444 else |
449 ++current; // Just do a narrow bucket, and keep trying. | 445 ++current; // Just do a narrow bucket, and keep trying. |
450 SetBucketRange(bucket_index, current); | 446 SetBucketRange(bucket_index, current); |
451 } | 447 } |
452 ResetRangeChecksum(); | 448 ResetRangeChecksum(); |
453 | 449 |
454 DCHECK_EQ(bucket_count(), bucket_index); | 450 DCHECK_EQ(bucket_count(), bucket_index); |
455 } | 451 } |
456 | 452 |
| 453 bool Histogram::PrintEmptyBucket(size_t index) const { |
| 454 return true; |
| 455 } |
| 456 |
457 size_t Histogram::BucketIndex(Sample value) const { | 457 size_t Histogram::BucketIndex(Sample value) const { |
458 // Use simple binary search. This is very general, but there are better | 458 // Use simple binary search. This is very general, but there are better |
459 // approaches if we knew that the buckets were linearly distributed. | 459 // approaches if we knew that the buckets were linearly distributed. |
460 DCHECK_LE(ranges(0), value); | 460 DCHECK_LE(ranges(0), value); |
461 DCHECK_GT(ranges(bucket_count()), value); | 461 DCHECK_GT(ranges(bucket_count()), value); |
462 size_t under = 0; | 462 size_t under = 0; |
463 size_t over = bucket_count(); | 463 size_t over = bucket_count(); |
464 size_t mid; | 464 size_t mid; |
465 | 465 |
466 do { | 466 do { |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
784 if (minimum < 1) | 784 if (minimum < 1) |
785 minimum = 1; | 785 minimum = 1; |
786 if (maximum > kSampleType_MAX - 1) | 786 if (maximum > kSampleType_MAX - 1) |
787 maximum = kSampleType_MAX - 1; | 787 maximum = kSampleType_MAX - 1; |
788 | 788 |
789 if (!StatisticsRecorder::FindHistogram(name, &histogram)) { | 789 if (!StatisticsRecorder::FindHistogram(name, &histogram)) { |
790 LinearHistogram* linear_histogram = | 790 LinearHistogram* linear_histogram = |
791 new LinearHistogram(name, minimum, maximum, bucket_count); | 791 new LinearHistogram(name, minimum, maximum, bucket_count); |
792 linear_histogram->InitializeBucketRange(); | 792 linear_histogram->InitializeBucketRange(); |
793 histogram = linear_histogram; | 793 histogram = linear_histogram; |
794 StatisticsRecorder::Register(&histogram); | 794 StatisticsRecorder::RegisterOrDiscardDuplicate(&histogram); |
795 } | 795 } |
796 | 796 |
797 DCHECK_EQ(LINEAR_HISTOGRAM, histogram->histogram_type()); | 797 DCHECK_EQ(LINEAR_HISTOGRAM, histogram->histogram_type()); |
798 DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count)); | 798 DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count)); |
799 histogram->SetFlags(flags); | 799 histogram->SetFlags(flags); |
800 return histogram; | 800 return histogram; |
801 } | 801 } |
802 | 802 |
803 scoped_refptr<Histogram> LinearHistogram::FactoryTimeGet( | 803 scoped_refptr<Histogram> LinearHistogram::FactoryTimeGet( |
804 const std::string& name, | 804 const std::string& name, |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
876 //------------------------------------------------------------------------------ | 876 //------------------------------------------------------------------------------ |
877 | 877 |
878 scoped_refptr<Histogram> BooleanHistogram::FactoryGet(const std::string& name, | 878 scoped_refptr<Histogram> BooleanHistogram::FactoryGet(const std::string& name, |
879 Flags flags) { | 879 Flags flags) { |
880 scoped_refptr<Histogram> histogram(NULL); | 880 scoped_refptr<Histogram> histogram(NULL); |
881 | 881 |
882 if (!StatisticsRecorder::FindHistogram(name, &histogram)) { | 882 if (!StatisticsRecorder::FindHistogram(name, &histogram)) { |
883 BooleanHistogram* boolean_histogram = new BooleanHistogram(name); | 883 BooleanHistogram* boolean_histogram = new BooleanHistogram(name); |
884 boolean_histogram->InitializeBucketRange(); | 884 boolean_histogram->InitializeBucketRange(); |
885 histogram = boolean_histogram; | 885 histogram = boolean_histogram; |
886 StatisticsRecorder::Register(&histogram); | 886 StatisticsRecorder::RegisterOrDiscardDuplicate(&histogram); |
887 } | 887 } |
888 | 888 |
889 DCHECK_EQ(BOOLEAN_HISTOGRAM, histogram->histogram_type()); | 889 DCHECK_EQ(BOOLEAN_HISTOGRAM, histogram->histogram_type()); |
890 histogram->SetFlags(flags); | 890 histogram->SetFlags(flags); |
891 return histogram; | 891 return histogram; |
892 } | 892 } |
893 | 893 |
894 Histogram::ClassType BooleanHistogram::histogram_type() const { | 894 Histogram::ClassType BooleanHistogram::histogram_type() const { |
895 return BOOLEAN_HISTOGRAM; | 895 return BOOLEAN_HISTOGRAM; |
896 } | 896 } |
(...skipping 26 matching lines...) Expand all Loading... |
923 // Note that we pushed a 0 in above, so for defensive code.... | 923 // Note that we pushed a 0 in above, so for defensive code.... |
924 ranges.push_back(1); // Put in some data so we can index to [1]. | 924 ranges.push_back(1); // Put in some data so we can index to [1]. |
925 } | 925 } |
926 | 926 |
927 DCHECK_LT(ranges.back(), kSampleType_MAX); | 927 DCHECK_LT(ranges.back(), kSampleType_MAX); |
928 | 928 |
929 if (!StatisticsRecorder::FindHistogram(name, &histogram)) { | 929 if (!StatisticsRecorder::FindHistogram(name, &histogram)) { |
930 CustomHistogram* custom_histogram = new CustomHistogram(name, ranges); | 930 CustomHistogram* custom_histogram = new CustomHistogram(name, ranges); |
931 custom_histogram->InitializedCustomBucketRange(ranges); | 931 custom_histogram->InitializedCustomBucketRange(ranges); |
932 histogram = custom_histogram; | 932 histogram = custom_histogram; |
933 StatisticsRecorder::Register(&histogram); | 933 StatisticsRecorder::RegisterOrDiscardDuplicate(&histogram); |
934 } | 934 } |
935 | 935 |
936 DCHECK_EQ(histogram->histogram_type(), CUSTOM_HISTOGRAM); | 936 DCHECK_EQ(histogram->histogram_type(), CUSTOM_HISTOGRAM); |
937 DCHECK(histogram->HasConstructorArguments(ranges[1], ranges.back(), | 937 DCHECK(histogram->HasConstructorArguments(ranges[1], ranges.back(), |
938 ranges.size())); | 938 ranges.size())); |
939 histogram->SetFlags(flags); | 939 histogram->SetFlags(flags); |
940 return histogram; | 940 return histogram; |
941 } | 941 } |
942 | 942 |
943 Histogram::ClassType CustomHistogram::histogram_type() const { | 943 Histogram::ClassType CustomHistogram::histogram_type() const { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1016 base::AutoLock auto_lock(*lock_); | 1016 base::AutoLock auto_lock(*lock_); |
1017 return NULL != histograms_; | 1017 return NULL != histograms_; |
1018 } | 1018 } |
1019 | 1019 |
1020 // Note: We can't accept a ref_ptr to |histogram| because we *might* not keep a | 1020 // Note: We can't accept a ref_ptr to |histogram| because we *might* not keep a |
1021 // reference, and we are called while in the Histogram constructor. In that | 1021 // reference, and we are called while in the Histogram constructor. In that |
1022 // scenario, a ref_ptr would have incremented the ref count when the histogram | 1022 // scenario, a ref_ptr would have incremented the ref count when the histogram |
1023 // was passed to us, decremented it when we returned, and the instance would be | 1023 // was passed to us, decremented it when we returned, and the instance would be |
1024 // destroyed before assignment (when value was returned by new). | 1024 // destroyed before assignment (when value was returned by new). |
1025 // static | 1025 // static |
1026 void StatisticsRecorder::Register(scoped_refptr<Histogram>* histogram) { | 1026 void StatisticsRecorder::RegisterOrDiscardDuplicate( |
| 1027 scoped_refptr<Histogram>* histogram) { |
1027 DCHECK((*histogram)->HasValidRangeChecksum()); | 1028 DCHECK((*histogram)->HasValidRangeChecksum()); |
1028 if (lock_ == NULL) | 1029 if (lock_ == NULL) |
1029 return; | 1030 return; |
1030 base::AutoLock auto_lock(*lock_); | 1031 base::AutoLock auto_lock(*lock_); |
1031 if (!histograms_) | 1032 if (!histograms_) |
1032 return; | 1033 return; |
1033 const std::string name = (*histogram)->histogram_name(); | 1034 const std::string name = (*histogram)->histogram_name(); |
1034 HistogramMap::iterator it = histograms_->find(name); | 1035 HistogramMap::iterator it = histograms_->find(name); |
1035 // Avoid overwriting a previous registration. | 1036 // Avoid overwriting a previous registration. |
1036 if (histograms_->end() == it) | 1037 if (histograms_->end() == it) |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1129 } | 1130 } |
1130 | 1131 |
1131 // static | 1132 // static |
1132 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; | 1133 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; |
1133 // static | 1134 // static |
1134 base::Lock* StatisticsRecorder::lock_ = NULL; | 1135 base::Lock* StatisticsRecorder::lock_ = NULL; |
1135 // static | 1136 // static |
1136 bool StatisticsRecorder::dump_on_exit_ = false; | 1137 bool StatisticsRecorder::dump_on_exit_ = false; |
1137 | 1138 |
1138 } // namespace base | 1139 } // namespace base |
OLD | NEW |