OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 int32_t flags) { | 268 int32_t flags) { |
269 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, | 269 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, |
270 flags); | 270 flags); |
271 } | 271 } |
272 | 272 |
273 std::unique_ptr<HistogramBase> Histogram::PersistentCreate( | 273 std::unique_ptr<HistogramBase> Histogram::PersistentCreate( |
274 const std::string& name, | 274 const std::string& name, |
275 Sample minimum, | 275 Sample minimum, |
276 Sample maximum, | 276 Sample maximum, |
277 const BucketRanges* ranges, | 277 const BucketRanges* ranges, |
278 const DelayedPersistentAllocation& counts, | 278 HistogramBase::AtomicCount* counts, |
279 const DelayedPersistentAllocation& logged_counts, | 279 HistogramBase::AtomicCount* logged_counts, |
| 280 uint32_t counts_size, |
280 HistogramSamples::Metadata* meta, | 281 HistogramSamples::Metadata* meta, |
281 HistogramSamples::Metadata* logged_meta) { | 282 HistogramSamples::Metadata* logged_meta) { |
282 return WrapUnique(new Histogram(name, minimum, maximum, ranges, counts, | 283 return WrapUnique(new Histogram(name, minimum, maximum, ranges, counts, |
283 logged_counts, meta, logged_meta)); | 284 logged_counts, counts_size, meta, |
| 285 logged_meta)); |
284 } | 286 } |
285 | 287 |
286 // Calculate what range of values are held in each bucket. | 288 // Calculate what range of values are held in each bucket. |
287 // We have to be careful that we don't pick a ratio between starting points in | 289 // We have to be careful that we don't pick a ratio between starting points in |
288 // consecutive buckets that is sooo small, that the integer bounds are the same | 290 // consecutive buckets that is sooo small, that the integer bounds are the same |
289 // (effectively making one bucket get no values). We need to avoid: | 291 // (effectively making one bucket get no values). We need to avoid: |
290 // ranges(i) == ranges(i + 1) | 292 // ranges(i) == ranges(i + 1) |
291 // To avoid that, we just do a fine-grained bucket width as far as we need to | 293 // To avoid that, we just do a fine-grained bucket width as far as we need to |
292 // until we get a ratio that moves us along at least 2 units at a time. From | 294 // until we get a ratio that moves us along at least 2 units at a time. From |
293 // that bucket onward we do use the exponential growth of buckets. | 295 // that bucket onward we do use the exponential growth of buckets. |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 declared_min_(minimum), | 505 declared_min_(minimum), |
504 declared_max_(maximum) { | 506 declared_max_(maximum) { |
505 if (ranges) | 507 if (ranges) |
506 samples_.reset(new SampleVector(HashMetricName(name), ranges)); | 508 samples_.reset(new SampleVector(HashMetricName(name), ranges)); |
507 } | 509 } |
508 | 510 |
509 Histogram::Histogram(const std::string& name, | 511 Histogram::Histogram(const std::string& name, |
510 Sample minimum, | 512 Sample minimum, |
511 Sample maximum, | 513 Sample maximum, |
512 const BucketRanges* ranges, | 514 const BucketRanges* ranges, |
513 const DelayedPersistentAllocation& counts, | 515 HistogramBase::AtomicCount* counts, |
514 const DelayedPersistentAllocation& logged_counts, | 516 HistogramBase::AtomicCount* logged_counts, |
| 517 uint32_t counts_size, |
515 HistogramSamples::Metadata* meta, | 518 HistogramSamples::Metadata* meta, |
516 HistogramSamples::Metadata* logged_meta) | 519 HistogramSamples::Metadata* logged_meta) |
517 : HistogramBase(name), | 520 : HistogramBase(name), |
518 bucket_ranges_(ranges), | 521 bucket_ranges_(ranges), |
519 declared_min_(minimum), | 522 declared_min_(minimum), |
520 declared_max_(maximum) { | 523 declared_max_(maximum) { |
521 if (ranges) { | 524 if (ranges) { |
522 samples_.reset( | 525 samples_.reset(new SampleVector(HashMetricName(name), |
523 new PersistentSampleVector(HashMetricName(name), ranges, meta, counts)); | 526 counts, counts_size, meta, ranges)); |
524 logged_samples_.reset(new PersistentSampleVector( | 527 logged_samples_.reset(new SampleVector(samples_->id(), logged_counts, |
525 samples_->id(), ranges, logged_meta, logged_counts)); | 528 counts_size, logged_meta, ranges)); |
526 } | 529 } |
527 } | 530 } |
528 | 531 |
529 Histogram::~Histogram() { | 532 Histogram::~Histogram() { |
530 } | 533 } |
531 | 534 |
532 bool Histogram::PrintEmptyBucket(uint32_t index) const { | 535 bool Histogram::PrintEmptyBucket(uint32_t index) const { |
533 return true; | 536 return true; |
534 } | 537 } |
535 | 538 |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
646 double current_size = GetBucketSize(current, i); | 649 double current_size = GetBucketSize(current, i); |
647 if (graph_it) | 650 if (graph_it) |
648 WriteAsciiBucketGraph(current_size, max_size, output); | 651 WriteAsciiBucketGraph(current_size, max_size, output); |
649 WriteAsciiBucketContext(past, current, remaining, i, output); | 652 WriteAsciiBucketContext(past, current, remaining, i, output); |
650 output->append(newline); | 653 output->append(newline); |
651 past += current; | 654 past += current; |
652 } | 655 } |
653 DCHECK_EQ(sample_count, past); | 656 DCHECK_EQ(sample_count, past); |
654 } | 657 } |
655 | 658 |
656 double Histogram::GetPeakBucketSize(const SampleVectorBase& samples) const { | 659 double Histogram::GetPeakBucketSize(const SampleVector& samples) const { |
657 double max = 0; | 660 double max = 0; |
658 for (uint32_t i = 0; i < bucket_count() ; ++i) { | 661 for (uint32_t i = 0; i < bucket_count() ; ++i) { |
659 double current_size = GetBucketSize(samples.GetCountAtIndex(i), i); | 662 double current_size = GetBucketSize(samples.GetCountAtIndex(i), i); |
660 if (current_size > max) | 663 if (current_size > max) |
661 max = current_size; | 664 max = current_size; |
662 } | 665 } |
663 return max; | 666 return max; |
664 } | 667 } |
665 | 668 |
666 void Histogram::WriteAsciiHeader(const SampleVectorBase& samples, | 669 void Histogram::WriteAsciiHeader(const SampleVector& samples, |
667 Count sample_count, | 670 Count sample_count, |
668 std::string* output) const { | 671 std::string* output) const { |
669 StringAppendF(output, | 672 StringAppendF(output, |
670 "Histogram: %s recorded %d samples", | 673 "Histogram: %s recorded %d samples", |
671 histogram_name().c_str(), | 674 histogram_name().c_str(), |
672 sample_count); | 675 sample_count); |
673 if (sample_count == 0) { | 676 if (sample_count == 0) { |
674 DCHECK_EQ(samples.sum(), 0); | 677 DCHECK_EQ(samples.sum(), 0); |
675 } else { | 678 } else { |
676 double mean = static_cast<float>(samples.sum()) / sample_count; | 679 double mean = static_cast<float>(samples.sum()) / sample_count; |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
805 int32_t flags) { | 808 int32_t flags) { |
806 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, | 809 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, |
807 flags); | 810 flags); |
808 } | 811 } |
809 | 812 |
810 std::unique_ptr<HistogramBase> LinearHistogram::PersistentCreate( | 813 std::unique_ptr<HistogramBase> LinearHistogram::PersistentCreate( |
811 const std::string& name, | 814 const std::string& name, |
812 Sample minimum, | 815 Sample minimum, |
813 Sample maximum, | 816 Sample maximum, |
814 const BucketRanges* ranges, | 817 const BucketRanges* ranges, |
815 const DelayedPersistentAllocation& counts, | 818 HistogramBase::AtomicCount* counts, |
816 const DelayedPersistentAllocation& logged_counts, | 819 HistogramBase::AtomicCount* logged_counts, |
| 820 uint32_t counts_size, |
817 HistogramSamples::Metadata* meta, | 821 HistogramSamples::Metadata* meta, |
818 HistogramSamples::Metadata* logged_meta) { | 822 HistogramSamples::Metadata* logged_meta) { |
819 return WrapUnique(new LinearHistogram(name, minimum, maximum, ranges, counts, | 823 return WrapUnique(new LinearHistogram(name, minimum, maximum, ranges, |
820 logged_counts, meta, logged_meta)); | 824 counts, logged_counts, |
| 825 counts_size, meta, logged_meta)); |
821 } | 826 } |
822 | 827 |
823 HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( | 828 HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( |
824 const std::string& name, | 829 const std::string& name, |
825 Sample minimum, | 830 Sample minimum, |
826 Sample maximum, | 831 Sample maximum, |
827 uint32_t bucket_count, | 832 uint32_t bucket_count, |
828 int32_t flags, | 833 int32_t flags, |
829 const DescriptionPair descriptions[]) { | 834 const DescriptionPair descriptions[]) { |
830 bool valid_arguments = Histogram::InspectConstructionArguments( | 835 bool valid_arguments = Histogram::InspectConstructionArguments( |
831 name, &minimum, &maximum, &bucket_count); | 836 name, &minimum, &maximum, &bucket_count); |
832 DCHECK(valid_arguments); | 837 DCHECK(valid_arguments); |
833 | 838 |
834 return Factory(name, minimum, maximum, bucket_count, flags, descriptions) | 839 return Factory(name, minimum, maximum, bucket_count, flags, descriptions) |
835 .Build(); | 840 .Build(); |
836 } | 841 } |
837 | 842 |
838 HistogramType LinearHistogram::GetHistogramType() const { | 843 HistogramType LinearHistogram::GetHistogramType() const { |
839 return LINEAR_HISTOGRAM; | 844 return LINEAR_HISTOGRAM; |
840 } | 845 } |
841 | 846 |
842 LinearHistogram::LinearHistogram(const std::string& name, | 847 LinearHistogram::LinearHistogram(const std::string& name, |
843 Sample minimum, | 848 Sample minimum, |
844 Sample maximum, | 849 Sample maximum, |
845 const BucketRanges* ranges) | 850 const BucketRanges* ranges) |
846 : Histogram(name, minimum, maximum, ranges) { | 851 : Histogram(name, minimum, maximum, ranges) { |
847 } | 852 } |
848 | 853 |
849 LinearHistogram::LinearHistogram( | 854 LinearHistogram::LinearHistogram(const std::string& name, |
850 const std::string& name, | 855 Sample minimum, |
851 Sample minimum, | 856 Sample maximum, |
852 Sample maximum, | 857 const BucketRanges* ranges, |
853 const BucketRanges* ranges, | 858 HistogramBase::AtomicCount* counts, |
854 const DelayedPersistentAllocation& counts, | 859 HistogramBase::AtomicCount* logged_counts, |
855 const DelayedPersistentAllocation& logged_counts, | 860 uint32_t counts_size, |
856 HistogramSamples::Metadata* meta, | 861 HistogramSamples::Metadata* meta, |
857 HistogramSamples::Metadata* logged_meta) | 862 HistogramSamples::Metadata* logged_meta) |
858 : Histogram(name, | 863 : Histogram(name, minimum, maximum, ranges, counts, logged_counts, |
859 minimum, | 864 counts_size, meta, logged_meta) {} |
860 maximum, | |
861 ranges, | |
862 counts, | |
863 logged_counts, | |
864 meta, | |
865 logged_meta) {} | |
866 | 865 |
867 double LinearHistogram::GetBucketSize(Count current, uint32_t i) const { | 866 double LinearHistogram::GetBucketSize(Count current, uint32_t i) const { |
868 DCHECK_GT(ranges(i + 1), ranges(i)); | 867 DCHECK_GT(ranges(i + 1), ranges(i)); |
869 // Adjacent buckets with different widths would have "surprisingly" many (few) | 868 // Adjacent buckets with different widths would have "surprisingly" many (few) |
870 // samples in a histogram if we didn't normalize this way. | 869 // samples in a histogram if we didn't normalize this way. |
871 double denominator = ranges(i + 1) - ranges(i); | 870 double denominator = ranges(i + 1) - ranges(i); |
872 return current/denominator; | 871 return current/denominator; |
873 } | 872 } |
874 | 873 |
875 const std::string LinearHistogram::GetAsciiBucketRange(uint32_t i) const { | 874 const std::string LinearHistogram::GetAsciiBucketRange(uint32_t i) const { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
955 return Factory(name, flags).Build(); | 954 return Factory(name, flags).Build(); |
956 } | 955 } |
957 | 956 |
958 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32_t flags) { | 957 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32_t flags) { |
959 return FactoryGet(std::string(name), flags); | 958 return FactoryGet(std::string(name), flags); |
960 } | 959 } |
961 | 960 |
962 std::unique_ptr<HistogramBase> BooleanHistogram::PersistentCreate( | 961 std::unique_ptr<HistogramBase> BooleanHistogram::PersistentCreate( |
963 const std::string& name, | 962 const std::string& name, |
964 const BucketRanges* ranges, | 963 const BucketRanges* ranges, |
965 const DelayedPersistentAllocation& counts, | 964 HistogramBase::AtomicCount* counts, |
966 const DelayedPersistentAllocation& logged_counts, | 965 HistogramBase::AtomicCount* logged_counts, |
967 HistogramSamples::Metadata* meta, | 966 HistogramSamples::Metadata* meta, |
968 HistogramSamples::Metadata* logged_meta) { | 967 HistogramSamples::Metadata* logged_meta) { |
969 return WrapUnique(new BooleanHistogram(name, ranges, counts, logged_counts, | 968 return WrapUnique(new BooleanHistogram( |
970 meta, logged_meta)); | 969 name, ranges, counts, logged_counts, meta, logged_meta)); |
971 } | 970 } |
972 | 971 |
973 HistogramType BooleanHistogram::GetHistogramType() const { | 972 HistogramType BooleanHistogram::GetHistogramType() const { |
974 return BOOLEAN_HISTOGRAM; | 973 return BOOLEAN_HISTOGRAM; |
975 } | 974 } |
976 | 975 |
977 BooleanHistogram::BooleanHistogram(const std::string& name, | 976 BooleanHistogram::BooleanHistogram(const std::string& name, |
978 const BucketRanges* ranges) | 977 const BucketRanges* ranges) |
979 : LinearHistogram(name, 1, 2, ranges) {} | 978 : LinearHistogram(name, 1, 2, ranges) {} |
980 | 979 |
981 BooleanHistogram::BooleanHistogram( | 980 BooleanHistogram::BooleanHistogram(const std::string& name, |
982 const std::string& name, | 981 const BucketRanges* ranges, |
983 const BucketRanges* ranges, | 982 HistogramBase::AtomicCount* counts, |
984 const DelayedPersistentAllocation& counts, | 983 HistogramBase::AtomicCount* logged_counts, |
985 const DelayedPersistentAllocation& logged_counts, | 984 HistogramSamples::Metadata* meta, |
986 HistogramSamples::Metadata* meta, | 985 HistogramSamples::Metadata* logged_meta) |
987 HistogramSamples::Metadata* logged_meta) | 986 : LinearHistogram(name, 1, 2, ranges, counts, logged_counts, 2, meta, |
988 : LinearHistogram(name, | |
989 1, | |
990 2, | |
991 ranges, | |
992 counts, | |
993 logged_counts, | |
994 meta, | |
995 logged_meta) {} | 987 logged_meta) {} |
996 | 988 |
997 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { | 989 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { |
998 std::string histogram_name; | 990 std::string histogram_name; |
999 int flags; | 991 int flags; |
1000 int declared_min; | 992 int declared_min; |
1001 int declared_max; | 993 int declared_max; |
1002 uint32_t bucket_count; | 994 uint32_t bucket_count; |
1003 uint32_t range_checksum; | 995 uint32_t range_checksum; |
1004 | 996 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1069 HistogramBase* CustomHistogram::FactoryGet( | 1061 HistogramBase* CustomHistogram::FactoryGet( |
1070 const char* name, | 1062 const char* name, |
1071 const std::vector<Sample>& custom_ranges, | 1063 const std::vector<Sample>& custom_ranges, |
1072 int32_t flags) { | 1064 int32_t flags) { |
1073 return FactoryGet(std::string(name), custom_ranges, flags); | 1065 return FactoryGet(std::string(name), custom_ranges, flags); |
1074 } | 1066 } |
1075 | 1067 |
1076 std::unique_ptr<HistogramBase> CustomHistogram::PersistentCreate( | 1068 std::unique_ptr<HistogramBase> CustomHistogram::PersistentCreate( |
1077 const std::string& name, | 1069 const std::string& name, |
1078 const BucketRanges* ranges, | 1070 const BucketRanges* ranges, |
1079 const DelayedPersistentAllocation& counts, | 1071 HistogramBase::AtomicCount* counts, |
1080 const DelayedPersistentAllocation& logged_counts, | 1072 HistogramBase::AtomicCount* logged_counts, |
| 1073 uint32_t counts_size, |
1081 HistogramSamples::Metadata* meta, | 1074 HistogramSamples::Metadata* meta, |
1082 HistogramSamples::Metadata* logged_meta) { | 1075 HistogramSamples::Metadata* logged_meta) { |
1083 return WrapUnique(new CustomHistogram(name, ranges, counts, logged_counts, | 1076 return WrapUnique(new CustomHistogram( |
1084 meta, logged_meta)); | 1077 name, ranges, counts, logged_counts, counts_size, meta, logged_meta)); |
1085 } | 1078 } |
1086 | 1079 |
1087 HistogramType CustomHistogram::GetHistogramType() const { | 1080 HistogramType CustomHistogram::GetHistogramType() const { |
1088 return CUSTOM_HISTOGRAM; | 1081 return CUSTOM_HISTOGRAM; |
1089 } | 1082 } |
1090 | 1083 |
1091 // static | 1084 // static |
1092 std::vector<Sample> CustomHistogram::ArrayToCustomRanges( | 1085 std::vector<Sample> CustomHistogram::ArrayToCustomRanges( |
1093 const Sample* values, uint32_t num_values) { | 1086 const Sample* values, uint32_t num_values) { |
1094 std::vector<Sample> all_values; | 1087 std::vector<Sample> all_values; |
1095 for (uint32_t i = 0; i < num_values; ++i) { | 1088 for (uint32_t i = 0; i < num_values; ++i) { |
1096 Sample value = values[i]; | 1089 Sample value = values[i]; |
1097 all_values.push_back(value); | 1090 all_values.push_back(value); |
1098 | 1091 |
1099 // Ensure that a guard bucket is added. If we end up with duplicate | 1092 // Ensure that a guard bucket is added. If we end up with duplicate |
1100 // values, FactoryGet will take care of removing them. | 1093 // values, FactoryGet will take care of removing them. |
1101 all_values.push_back(value + 1); | 1094 all_values.push_back(value + 1); |
1102 } | 1095 } |
1103 return all_values; | 1096 return all_values; |
1104 } | 1097 } |
1105 | 1098 |
1106 CustomHistogram::CustomHistogram(const std::string& name, | 1099 CustomHistogram::CustomHistogram(const std::string& name, |
1107 const BucketRanges* ranges) | 1100 const BucketRanges* ranges) |
1108 : Histogram(name, | 1101 : Histogram(name, |
1109 ranges->range(1), | 1102 ranges->range(1), |
1110 ranges->range(ranges->bucket_count() - 1), | 1103 ranges->range(ranges->bucket_count() - 1), |
1111 ranges) {} | 1104 ranges) {} |
1112 | 1105 |
1113 CustomHistogram::CustomHistogram( | 1106 CustomHistogram::CustomHistogram(const std::string& name, |
1114 const std::string& name, | 1107 const BucketRanges* ranges, |
1115 const BucketRanges* ranges, | 1108 HistogramBase::AtomicCount* counts, |
1116 const DelayedPersistentAllocation& counts, | 1109 HistogramBase::AtomicCount* logged_counts, |
1117 const DelayedPersistentAllocation& logged_counts, | 1110 uint32_t counts_size, |
1118 HistogramSamples::Metadata* meta, | 1111 HistogramSamples::Metadata* meta, |
1119 HistogramSamples::Metadata* logged_meta) | 1112 HistogramSamples::Metadata* logged_meta) |
1120 : Histogram(name, | 1113 : Histogram(name, |
1121 ranges->range(1), | 1114 ranges->range(1), |
1122 ranges->range(ranges->bucket_count() - 1), | 1115 ranges->range(ranges->bucket_count() - 1), |
1123 ranges, | 1116 ranges, |
1124 counts, | 1117 counts, |
1125 logged_counts, | 1118 logged_counts, |
| 1119 counts_size, |
1126 meta, | 1120 meta, |
1127 logged_meta) {} | 1121 logged_meta) {} |
1128 | 1122 |
1129 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { | 1123 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { |
1130 if (!Histogram::SerializeInfoImpl(pickle)) | 1124 if (!Histogram::SerializeInfoImpl(pickle)) |
1131 return false; | 1125 return false; |
1132 | 1126 |
1133 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't | 1127 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't |
1134 // write them. | 1128 // write them. |
1135 for (uint32_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { | 1129 for (uint32_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1184 Sample sample = custom_ranges[i]; | 1178 Sample sample = custom_ranges[i]; |
1185 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) | 1179 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) |
1186 return false; | 1180 return false; |
1187 if (sample != 0) | 1181 if (sample != 0) |
1188 has_valid_range = true; | 1182 has_valid_range = true; |
1189 } | 1183 } |
1190 return has_valid_range; | 1184 return has_valid_range; |
1191 } | 1185 } |
1192 | 1186 |
1193 } // namespace base | 1187 } // namespace base |
OLD | NEW |