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 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 int32_t flags) { | 269 int32_t flags) { |
270 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, | 270 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, |
271 flags); | 271 flags); |
272 } | 272 } |
273 | 273 |
274 std::unique_ptr<HistogramBase> Histogram::PersistentCreate( | 274 std::unique_ptr<HistogramBase> Histogram::PersistentCreate( |
275 const std::string& name, | 275 const std::string& name, |
276 Sample minimum, | 276 Sample minimum, |
277 Sample maximum, | 277 Sample maximum, |
278 const BucketRanges* ranges, | 278 const BucketRanges* ranges, |
279 HistogramBase::AtomicCount* counts, | 279 const DelayedPersistentAllocation& counts, |
280 HistogramBase::AtomicCount* logged_counts, | 280 const DelayedPersistentAllocation& logged_counts, |
281 uint32_t counts_size, | |
282 HistogramSamples::Metadata* meta, | 281 HistogramSamples::Metadata* meta, |
283 HistogramSamples::Metadata* logged_meta) { | 282 HistogramSamples::Metadata* logged_meta) { |
284 return WrapUnique(new Histogram(name, minimum, maximum, ranges, counts, | 283 return WrapUnique(new Histogram(name, minimum, maximum, ranges, counts, |
285 logged_counts, counts_size, meta, | 284 logged_counts, meta, logged_meta)); |
286 logged_meta)); | |
287 } | 285 } |
288 | 286 |
289 // Calculate what range of values are held in each bucket. | 287 // Calculate what range of values are held in each bucket. |
290 // We have to be careful that we don't pick a ratio between starting points in | 288 // We have to be careful that we don't pick a ratio between starting points in |
291 // consecutive buckets that is sooo small, that the integer bounds are the same | 289 // consecutive buckets that is sooo small, that the integer bounds are the same |
292 // (effectively making one bucket get no values). We need to avoid: | 290 // (effectively making one bucket get no values). We need to avoid: |
293 // ranges(i) == ranges(i + 1) | 291 // ranges(i) == ranges(i + 1) |
294 // To avoid that, we just do a fine-grained bucket width as far as we need to | 292 // To avoid that, we just do a fine-grained bucket width as far as we need to |
295 // until we get a ratio that moves us along at least 2 units at a time. From | 293 // until we get a ratio that moves us along at least 2 units at a time. From |
296 // that bucket onward we do use the exponential growth of buckets. | 294 // that bucket onward we do use the exponential growth of buckets. |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 declared_min_(minimum), | 522 declared_min_(minimum), |
525 declared_max_(maximum) { | 523 declared_max_(maximum) { |
526 if (ranges) | 524 if (ranges) |
527 samples_.reset(new SampleVector(HashMetricName(name), ranges)); | 525 samples_.reset(new SampleVector(HashMetricName(name), ranges)); |
528 } | 526 } |
529 | 527 |
530 Histogram::Histogram(const std::string& name, | 528 Histogram::Histogram(const std::string& name, |
531 Sample minimum, | 529 Sample minimum, |
532 Sample maximum, | 530 Sample maximum, |
533 const BucketRanges* ranges, | 531 const BucketRanges* ranges, |
534 HistogramBase::AtomicCount* counts, | 532 const DelayedPersistentAllocation& counts, |
535 HistogramBase::AtomicCount* logged_counts, | 533 const DelayedPersistentAllocation& logged_counts, |
536 uint32_t counts_size, | |
537 HistogramSamples::Metadata* meta, | 534 HistogramSamples::Metadata* meta, |
538 HistogramSamples::Metadata* logged_meta) | 535 HistogramSamples::Metadata* logged_meta) |
539 : HistogramBase(name), | 536 : HistogramBase(name), |
540 bucket_ranges_(ranges), | 537 bucket_ranges_(ranges), |
541 declared_min_(minimum), | 538 declared_min_(minimum), |
542 declared_max_(maximum) { | 539 declared_max_(maximum) { |
543 if (ranges) { | 540 if (ranges) { |
544 samples_.reset(new SampleVector(HashMetricName(name), | 541 samples_.reset( |
545 counts, counts_size, meta, ranges)); | 542 new PersistentSampleVector(HashMetricName(name), ranges, meta, counts)); |
546 logged_samples_.reset(new SampleVector(samples_->id(), logged_counts, | 543 logged_samples_.reset(new PersistentSampleVector( |
547 counts_size, logged_meta, ranges)); | 544 samples_->id(), ranges, logged_meta, logged_counts)); |
548 } | 545 } |
549 } | 546 } |
550 | 547 |
551 Histogram::~Histogram() { | 548 Histogram::~Histogram() { |
552 } | 549 } |
553 | 550 |
554 bool Histogram::PrintEmptyBucket(uint32_t index) const { | 551 bool Histogram::PrintEmptyBucket(uint32_t index) const { |
555 return true; | 552 return true; |
556 } | 553 } |
557 | 554 |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 double current_size = GetBucketSize(current, i); | 665 double current_size = GetBucketSize(current, i); |
669 if (graph_it) | 666 if (graph_it) |
670 WriteAsciiBucketGraph(current_size, max_size, output); | 667 WriteAsciiBucketGraph(current_size, max_size, output); |
671 WriteAsciiBucketContext(past, current, remaining, i, output); | 668 WriteAsciiBucketContext(past, current, remaining, i, output); |
672 output->append(newline); | 669 output->append(newline); |
673 past += current; | 670 past += current; |
674 } | 671 } |
675 DCHECK_EQ(sample_count, past); | 672 DCHECK_EQ(sample_count, past); |
676 } | 673 } |
677 | 674 |
678 double Histogram::GetPeakBucketSize(const SampleVector& samples) const { | 675 double Histogram::GetPeakBucketSize(const SampleVectorBase& samples) const { |
679 double max = 0; | 676 double max = 0; |
680 for (uint32_t i = 0; i < bucket_count() ; ++i) { | 677 for (uint32_t i = 0; i < bucket_count() ; ++i) { |
681 double current_size = GetBucketSize(samples.GetCountAtIndex(i), i); | 678 double current_size = GetBucketSize(samples.GetCountAtIndex(i), i); |
682 if (current_size > max) | 679 if (current_size > max) |
683 max = current_size; | 680 max = current_size; |
684 } | 681 } |
685 return max; | 682 return max; |
686 } | 683 } |
687 | 684 |
688 void Histogram::WriteAsciiHeader(const SampleVector& samples, | 685 void Histogram::WriteAsciiHeader(const SampleVectorBase& samples, |
689 Count sample_count, | 686 Count sample_count, |
690 std::string* output) const { | 687 std::string* output) const { |
691 StringAppendF(output, | 688 StringAppendF(output, |
692 "Histogram: %s recorded %d samples", | 689 "Histogram: %s recorded %d samples", |
693 histogram_name().c_str(), | 690 histogram_name().c_str(), |
694 sample_count); | 691 sample_count); |
695 if (sample_count == 0) { | 692 if (sample_count == 0) { |
696 DCHECK_EQ(samples.sum(), 0); | 693 DCHECK_EQ(samples.sum(), 0); |
697 } else { | 694 } else { |
698 double mean = static_cast<float>(samples.sum()) / sample_count; | 695 double mean = static_cast<float>(samples.sum()) / sample_count; |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
827 int32_t flags) { | 824 int32_t flags) { |
828 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, | 825 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, |
829 flags); | 826 flags); |
830 } | 827 } |
831 | 828 |
832 std::unique_ptr<HistogramBase> LinearHistogram::PersistentCreate( | 829 std::unique_ptr<HistogramBase> LinearHistogram::PersistentCreate( |
833 const std::string& name, | 830 const std::string& name, |
834 Sample minimum, | 831 Sample minimum, |
835 Sample maximum, | 832 Sample maximum, |
836 const BucketRanges* ranges, | 833 const BucketRanges* ranges, |
837 HistogramBase::AtomicCount* counts, | 834 const DelayedPersistentAllocation& counts, |
838 HistogramBase::AtomicCount* logged_counts, | 835 const DelayedPersistentAllocation& logged_counts, |
839 uint32_t counts_size, | |
840 HistogramSamples::Metadata* meta, | 836 HistogramSamples::Metadata* meta, |
841 HistogramSamples::Metadata* logged_meta) { | 837 HistogramSamples::Metadata* logged_meta) { |
842 return WrapUnique(new LinearHistogram(name, minimum, maximum, ranges, | 838 return WrapUnique(new LinearHistogram(name, minimum, maximum, ranges, counts, |
843 counts, logged_counts, | 839 logged_counts, meta, logged_meta)); |
844 counts_size, meta, logged_meta)); | |
845 } | 840 } |
846 | 841 |
847 HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( | 842 HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( |
848 const std::string& name, | 843 const std::string& name, |
849 Sample minimum, | 844 Sample minimum, |
850 Sample maximum, | 845 Sample maximum, |
851 uint32_t bucket_count, | 846 uint32_t bucket_count, |
852 int32_t flags, | 847 int32_t flags, |
853 const DescriptionPair descriptions[]) { | 848 const DescriptionPair descriptions[]) { |
854 bool valid_arguments = Histogram::InspectConstructionArguments( | 849 bool valid_arguments = Histogram::InspectConstructionArguments( |
855 name, &minimum, &maximum, &bucket_count); | 850 name, &minimum, &maximum, &bucket_count); |
856 DCHECK(valid_arguments); | 851 DCHECK(valid_arguments); |
857 | 852 |
858 return Factory(name, minimum, maximum, bucket_count, flags, descriptions) | 853 return Factory(name, minimum, maximum, bucket_count, flags, descriptions) |
859 .Build(); | 854 .Build(); |
860 } | 855 } |
861 | 856 |
862 HistogramType LinearHistogram::GetHistogramType() const { | 857 HistogramType LinearHistogram::GetHistogramType() const { |
863 return LINEAR_HISTOGRAM; | 858 return LINEAR_HISTOGRAM; |
864 } | 859 } |
865 | 860 |
866 LinearHistogram::LinearHistogram(const std::string& name, | 861 LinearHistogram::LinearHistogram(const std::string& name, |
867 Sample minimum, | 862 Sample minimum, |
868 Sample maximum, | 863 Sample maximum, |
869 const BucketRanges* ranges) | 864 const BucketRanges* ranges) |
870 : Histogram(name, minimum, maximum, ranges) { | 865 : Histogram(name, minimum, maximum, ranges) { |
871 } | 866 } |
872 | 867 |
873 LinearHistogram::LinearHistogram(const std::string& name, | 868 LinearHistogram::LinearHistogram( |
874 Sample minimum, | 869 const std::string& name, |
875 Sample maximum, | 870 Sample minimum, |
876 const BucketRanges* ranges, | 871 Sample maximum, |
877 HistogramBase::AtomicCount* counts, | 872 const BucketRanges* ranges, |
878 HistogramBase::AtomicCount* logged_counts, | 873 const DelayedPersistentAllocation& counts, |
879 uint32_t counts_size, | 874 const DelayedPersistentAllocation& logged_counts, |
880 HistogramSamples::Metadata* meta, | 875 HistogramSamples::Metadata* meta, |
881 HistogramSamples::Metadata* logged_meta) | 876 HistogramSamples::Metadata* logged_meta) |
882 : Histogram(name, minimum, maximum, ranges, counts, logged_counts, | 877 : Histogram(name, |
883 counts_size, meta, logged_meta) {} | 878 minimum, |
| 879 maximum, |
| 880 ranges, |
| 881 counts, |
| 882 logged_counts, |
| 883 meta, |
| 884 logged_meta) {} |
884 | 885 |
885 double LinearHistogram::GetBucketSize(Count current, uint32_t i) const { | 886 double LinearHistogram::GetBucketSize(Count current, uint32_t i) const { |
886 DCHECK_GT(ranges(i + 1), ranges(i)); | 887 DCHECK_GT(ranges(i + 1), ranges(i)); |
887 // Adjacent buckets with different widths would have "surprisingly" many (few) | 888 // Adjacent buckets with different widths would have "surprisingly" many (few) |
888 // samples in a histogram if we didn't normalize this way. | 889 // samples in a histogram if we didn't normalize this way. |
889 double denominator = ranges(i + 1) - ranges(i); | 890 double denominator = ranges(i + 1) - ranges(i); |
890 return current/denominator; | 891 return current/denominator; |
891 } | 892 } |
892 | 893 |
893 const std::string LinearHistogram::GetAsciiBucketRange(uint32_t i) const { | 894 const std::string LinearHistogram::GetAsciiBucketRange(uint32_t i) const { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
973 return Factory(name, flags).Build(); | 974 return Factory(name, flags).Build(); |
974 } | 975 } |
975 | 976 |
976 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32_t flags) { | 977 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32_t flags) { |
977 return FactoryGet(std::string(name), flags); | 978 return FactoryGet(std::string(name), flags); |
978 } | 979 } |
979 | 980 |
980 std::unique_ptr<HistogramBase> BooleanHistogram::PersistentCreate( | 981 std::unique_ptr<HistogramBase> BooleanHistogram::PersistentCreate( |
981 const std::string& name, | 982 const std::string& name, |
982 const BucketRanges* ranges, | 983 const BucketRanges* ranges, |
983 HistogramBase::AtomicCount* counts, | 984 const DelayedPersistentAllocation& counts, |
984 HistogramBase::AtomicCount* logged_counts, | 985 const DelayedPersistentAllocation& logged_counts, |
985 HistogramSamples::Metadata* meta, | 986 HistogramSamples::Metadata* meta, |
986 HistogramSamples::Metadata* logged_meta) { | 987 HistogramSamples::Metadata* logged_meta) { |
987 return WrapUnique(new BooleanHistogram( | 988 return WrapUnique(new BooleanHistogram(name, ranges, counts, logged_counts, |
988 name, ranges, counts, logged_counts, meta, logged_meta)); | 989 meta, logged_meta)); |
989 } | 990 } |
990 | 991 |
991 HistogramType BooleanHistogram::GetHistogramType() const { | 992 HistogramType BooleanHistogram::GetHistogramType() const { |
992 return BOOLEAN_HISTOGRAM; | 993 return BOOLEAN_HISTOGRAM; |
993 } | 994 } |
994 | 995 |
995 BooleanHistogram::BooleanHistogram(const std::string& name, | 996 BooleanHistogram::BooleanHistogram(const std::string& name, |
996 const BucketRanges* ranges) | 997 const BucketRanges* ranges) |
997 : LinearHistogram(name, 1, 2, ranges) {} | 998 : LinearHistogram(name, 1, 2, ranges) {} |
998 | 999 |
999 BooleanHistogram::BooleanHistogram(const std::string& name, | 1000 BooleanHistogram::BooleanHistogram( |
1000 const BucketRanges* ranges, | 1001 const std::string& name, |
1001 HistogramBase::AtomicCount* counts, | 1002 const BucketRanges* ranges, |
1002 HistogramBase::AtomicCount* logged_counts, | 1003 const DelayedPersistentAllocation& counts, |
1003 HistogramSamples::Metadata* meta, | 1004 const DelayedPersistentAllocation& logged_counts, |
1004 HistogramSamples::Metadata* logged_meta) | 1005 HistogramSamples::Metadata* meta, |
1005 : LinearHistogram(name, 1, 2, ranges, counts, logged_counts, 2, meta, | 1006 HistogramSamples::Metadata* logged_meta) |
| 1007 : LinearHistogram(name, |
| 1008 1, |
| 1009 2, |
| 1010 ranges, |
| 1011 counts, |
| 1012 logged_counts, |
| 1013 meta, |
1006 logged_meta) {} | 1014 logged_meta) {} |
1007 | 1015 |
1008 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { | 1016 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { |
1009 std::string histogram_name; | 1017 std::string histogram_name; |
1010 int flags; | 1018 int flags; |
1011 int declared_min; | 1019 int declared_min; |
1012 int declared_max; | 1020 int declared_max; |
1013 uint32_t bucket_count; | 1021 uint32_t bucket_count; |
1014 uint32_t range_checksum; | 1022 uint32_t range_checksum; |
1015 | 1023 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1080 HistogramBase* CustomHistogram::FactoryGet( | 1088 HistogramBase* CustomHistogram::FactoryGet( |
1081 const char* name, | 1089 const char* name, |
1082 const std::vector<Sample>& custom_ranges, | 1090 const std::vector<Sample>& custom_ranges, |
1083 int32_t flags) { | 1091 int32_t flags) { |
1084 return FactoryGet(std::string(name), custom_ranges, flags); | 1092 return FactoryGet(std::string(name), custom_ranges, flags); |
1085 } | 1093 } |
1086 | 1094 |
1087 std::unique_ptr<HistogramBase> CustomHistogram::PersistentCreate( | 1095 std::unique_ptr<HistogramBase> CustomHistogram::PersistentCreate( |
1088 const std::string& name, | 1096 const std::string& name, |
1089 const BucketRanges* ranges, | 1097 const BucketRanges* ranges, |
1090 HistogramBase::AtomicCount* counts, | 1098 const DelayedPersistentAllocation& counts, |
1091 HistogramBase::AtomicCount* logged_counts, | 1099 const DelayedPersistentAllocation& logged_counts, |
1092 uint32_t counts_size, | |
1093 HistogramSamples::Metadata* meta, | 1100 HistogramSamples::Metadata* meta, |
1094 HistogramSamples::Metadata* logged_meta) { | 1101 HistogramSamples::Metadata* logged_meta) { |
1095 return WrapUnique(new CustomHistogram( | 1102 return WrapUnique(new CustomHistogram(name, ranges, counts, logged_counts, |
1096 name, ranges, counts, logged_counts, counts_size, meta, logged_meta)); | 1103 meta, logged_meta)); |
1097 } | 1104 } |
1098 | 1105 |
1099 HistogramType CustomHistogram::GetHistogramType() const { | 1106 HistogramType CustomHistogram::GetHistogramType() const { |
1100 return CUSTOM_HISTOGRAM; | 1107 return CUSTOM_HISTOGRAM; |
1101 } | 1108 } |
1102 | 1109 |
1103 // static | 1110 // static |
1104 std::vector<Sample> CustomHistogram::ArrayToCustomRanges( | 1111 std::vector<Sample> CustomHistogram::ArrayToCustomRanges( |
1105 const Sample* values, uint32_t num_values) { | 1112 const Sample* values, uint32_t num_values) { |
1106 std::vector<Sample> all_values; | 1113 std::vector<Sample> all_values; |
1107 for (uint32_t i = 0; i < num_values; ++i) { | 1114 for (uint32_t i = 0; i < num_values; ++i) { |
1108 Sample value = values[i]; | 1115 Sample value = values[i]; |
1109 all_values.push_back(value); | 1116 all_values.push_back(value); |
1110 | 1117 |
1111 // Ensure that a guard bucket is added. If we end up with duplicate | 1118 // Ensure that a guard bucket is added. If we end up with duplicate |
1112 // values, FactoryGet will take care of removing them. | 1119 // values, FactoryGet will take care of removing them. |
1113 all_values.push_back(value + 1); | 1120 all_values.push_back(value + 1); |
1114 } | 1121 } |
1115 return all_values; | 1122 return all_values; |
1116 } | 1123 } |
1117 | 1124 |
1118 CustomHistogram::CustomHistogram(const std::string& name, | 1125 CustomHistogram::CustomHistogram(const std::string& name, |
1119 const BucketRanges* ranges) | 1126 const BucketRanges* ranges) |
1120 : Histogram(name, | 1127 : Histogram(name, |
1121 ranges->range(1), | 1128 ranges->range(1), |
1122 ranges->range(ranges->bucket_count() - 1), | 1129 ranges->range(ranges->bucket_count() - 1), |
1123 ranges) {} | 1130 ranges) {} |
1124 | 1131 |
1125 CustomHistogram::CustomHistogram(const std::string& name, | 1132 CustomHistogram::CustomHistogram( |
1126 const BucketRanges* ranges, | 1133 const std::string& name, |
1127 HistogramBase::AtomicCount* counts, | 1134 const BucketRanges* ranges, |
1128 HistogramBase::AtomicCount* logged_counts, | 1135 const DelayedPersistentAllocation& counts, |
1129 uint32_t counts_size, | 1136 const DelayedPersistentAllocation& logged_counts, |
1130 HistogramSamples::Metadata* meta, | 1137 HistogramSamples::Metadata* meta, |
1131 HistogramSamples::Metadata* logged_meta) | 1138 HistogramSamples::Metadata* logged_meta) |
1132 : Histogram(name, | 1139 : Histogram(name, |
1133 ranges->range(1), | 1140 ranges->range(1), |
1134 ranges->range(ranges->bucket_count() - 1), | 1141 ranges->range(ranges->bucket_count() - 1), |
1135 ranges, | 1142 ranges, |
1136 counts, | 1143 counts, |
1137 logged_counts, | 1144 logged_counts, |
1138 counts_size, | |
1139 meta, | 1145 meta, |
1140 logged_meta) {} | 1146 logged_meta) {} |
1141 | 1147 |
1142 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { | 1148 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { |
1143 if (!Histogram::SerializeInfoImpl(pickle)) | 1149 if (!Histogram::SerializeInfoImpl(pickle)) |
1144 return false; | 1150 return false; |
1145 | 1151 |
1146 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't | 1152 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't |
1147 // write them. | 1153 // write them. |
1148 for (uint32_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { | 1154 for (uint32_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1197 Sample sample = custom_ranges[i]; | 1203 Sample sample = custom_ranges[i]; |
1198 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) | 1204 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) |
1199 return false; | 1205 return false; |
1200 if (sample != 0) | 1206 if (sample != 0) |
1201 has_valid_range = true; | 1207 has_valid_range = true; |
1202 } | 1208 } |
1203 return has_valid_range; | 1209 return has_valid_range; |
1204 } | 1210 } |
1205 | 1211 |
1206 } // namespace base | 1212 } // namespace base |
OLD | NEW |