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 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 | 260 |
261 HistogramBase* Histogram::FactoryTimeGet(const char* name, | 261 HistogramBase* Histogram::FactoryTimeGet(const char* name, |
262 TimeDelta minimum, | 262 TimeDelta minimum, |
263 TimeDelta maximum, | 263 TimeDelta maximum, |
264 uint32_t bucket_count, | 264 uint32_t bucket_count, |
265 int32_t flags) { | 265 int32_t flags) { |
266 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, | 266 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, |
267 flags); | 267 flags); |
268 } | 268 } |
269 | 269 |
270 HistogramBase* Histogram::PersistentGet(const std::string& name, | 270 HistogramBase* Histogram::PersistentGet( |
271 Sample minimum, | 271 const std::string& name, |
272 Sample maximum, | 272 Sample minimum, |
273 const BucketRanges* ranges, | 273 Sample maximum, |
274 HistogramBase::AtomicCount* counts, | 274 const BucketRanges* ranges, |
275 uint32_t counts_size, | 275 HistogramBase::AtomicCount* counts, |
276 HistogramSamples::Metadata* meta) { | 276 HistogramBase::AtomicCount* logged_counts, |
277 return new Histogram(name, minimum, maximum, ranges, counts, counts_size, | 277 uint32_t counts_size, |
278 meta); | 278 HistogramSamples::Metadata* meta, |
| 279 HistogramSamples::Metadata* logged_meta) { |
| 280 return new Histogram(name, minimum, maximum, ranges, counts, logged_counts, |
| 281 counts_size, meta, logged_meta); |
279 } | 282 } |
280 | 283 |
281 // Calculate what range of values are held in each bucket. | 284 // Calculate what range of values are held in each bucket. |
282 // We have to be careful that we don't pick a ratio between starting points in | 285 // We have to be careful that we don't pick a ratio between starting points in |
283 // consecutive buckets that is sooo small, that the integer bounds are the same | 286 // consecutive buckets that is sooo small, that the integer bounds are the same |
284 // (effectively making one bucket get no values). We need to avoid: | 287 // (effectively making one bucket get no values). We need to avoid: |
285 // ranges(i) == ranges(i + 1) | 288 // ranges(i) == ranges(i + 1) |
286 // To avoid that, we just do a fine-grained bucket width as far as we need to | 289 // To avoid that, we just do a fine-grained bucket width as far as we need to |
287 // until we get a ratio that moves us along at least 2 units at a time. From | 290 // until we get a ratio that moves us along at least 2 units at a time. From |
288 // that bucket onward we do use the exponential growth of buckets. | 291 // that bucket onward we do use the exponential growth of buckets. |
(...skipping 24 matching lines...) Expand all Loading... |
313 ++current; // Just do a narrow bucket, and keep trying. | 316 ++current; // Just do a narrow bucket, and keep trying. |
314 ranges->set_range(bucket_index, current); | 317 ranges->set_range(bucket_index, current); |
315 } | 318 } |
316 ranges->set_range(ranges->bucket_count(), HistogramBase::kSampleType_MAX); | 319 ranges->set_range(ranges->bucket_count(), HistogramBase::kSampleType_MAX); |
317 ranges->ResetChecksum(); | 320 ranges->ResetChecksum(); |
318 } | 321 } |
319 | 322 |
320 // static | 323 // static |
321 const int Histogram::kCommonRaceBasedCountMismatch = 5; | 324 const int Histogram::kCommonRaceBasedCountMismatch = 5; |
322 | 325 |
323 int Histogram::FindCorruption(const HistogramSamples& samples) const { | 326 uint32_t Histogram::FindCorruption(const HistogramSamples& samples) const { |
324 int inconsistencies = NO_INCONSISTENCIES; | 327 int inconsistencies = NO_INCONSISTENCIES; |
325 Sample previous_range = -1; // Bottom range is always 0. | 328 Sample previous_range = -1; // Bottom range is always 0. |
326 for (uint32_t index = 0; index < bucket_count(); ++index) { | 329 for (uint32_t index = 0; index < bucket_count(); ++index) { |
327 int new_range = ranges(index); | 330 int new_range = ranges(index); |
328 if (previous_range >= new_range) | 331 if (previous_range >= new_range) |
329 inconsistencies |= BUCKET_ORDER_ERROR; | 332 inconsistencies |= BUCKET_ORDER_ERROR; |
330 previous_range = new_range; | 333 previous_range = new_range; |
331 } | 334 } |
332 | 335 |
333 if (!bucket_ranges()->HasValidChecksum()) | 336 if (!bucket_ranges()->HasValidChecksum()) |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 } | 426 } |
424 samples_->Accumulate(value, count); | 427 samples_->Accumulate(value, count); |
425 | 428 |
426 FindAndRunCallback(value); | 429 FindAndRunCallback(value); |
427 } | 430 } |
428 | 431 |
429 scoped_ptr<HistogramSamples> Histogram::SnapshotSamples() const { | 432 scoped_ptr<HistogramSamples> Histogram::SnapshotSamples() const { |
430 return SnapshotSampleVector(); | 433 return SnapshotSampleVector(); |
431 } | 434 } |
432 | 435 |
| 436 scoped_ptr<HistogramSamples> Histogram::SnapshotDelta() { |
| 437 scoped_ptr<HistogramSamples> snapshot = SnapshotSampleVector(); |
| 438 if (!logged_samples_) { |
| 439 // If nothing has been previously logged, save this one as |
| 440 // |logged_samples_| and gather another snapshot to return. |
| 441 logged_samples_.swap(snapshot); |
| 442 return SnapshotSampleVector(); |
| 443 } |
| 444 |
| 445 // Subtract what was previously logged and update that information. |
| 446 snapshot->Subtract(*logged_samples_); |
| 447 logged_samples_->Add(*snapshot); |
| 448 return snapshot; |
| 449 } |
| 450 |
433 void Histogram::AddSamples(const HistogramSamples& samples) { | 451 void Histogram::AddSamples(const HistogramSamples& samples) { |
434 samples_->Add(samples); | 452 samples_->Add(samples); |
435 } | 453 } |
436 | 454 |
437 bool Histogram::AddSamplesFromPickle(PickleIterator* iter) { | 455 bool Histogram::AddSamplesFromPickle(PickleIterator* iter) { |
438 return samples_->AddFromPickle(iter); | 456 return samples_->AddFromPickle(iter); |
439 } | 457 } |
440 | 458 |
441 // The following methods provide a graphical histogram display. | 459 // The following methods provide a graphical histogram display. |
442 void Histogram::WriteHTMLGraph(std::string* output) const { | 460 void Histogram::WriteHTMLGraph(std::string* output) const { |
(...skipping 27 matching lines...) Expand all Loading... |
470 declared_max_(maximum) { | 488 declared_max_(maximum) { |
471 if (ranges) | 489 if (ranges) |
472 samples_.reset(new SampleVector(HashMetricName(name), ranges)); | 490 samples_.reset(new SampleVector(HashMetricName(name), ranges)); |
473 } | 491 } |
474 | 492 |
475 Histogram::Histogram(const std::string& name, | 493 Histogram::Histogram(const std::string& name, |
476 Sample minimum, | 494 Sample minimum, |
477 Sample maximum, | 495 Sample maximum, |
478 const BucketRanges* ranges, | 496 const BucketRanges* ranges, |
479 HistogramBase::AtomicCount* counts, | 497 HistogramBase::AtomicCount* counts, |
| 498 HistogramBase::AtomicCount* logged_counts, |
480 uint32_t counts_size, | 499 uint32_t counts_size, |
481 HistogramSamples::Metadata* meta) | 500 HistogramSamples::Metadata* meta, |
| 501 HistogramSamples::Metadata* logged_meta) |
482 : HistogramBase(name), | 502 : HistogramBase(name), |
483 bucket_ranges_(ranges), | 503 bucket_ranges_(ranges), |
484 declared_min_(minimum), | 504 declared_min_(minimum), |
485 declared_max_(maximum) { | 505 declared_max_(maximum) { |
486 if (ranges) { | 506 if (ranges) { |
487 samples_.reset(new SampleVector(HashMetricName(name), | 507 samples_.reset(new SampleVector(HashMetricName(name), |
488 counts, counts_size, meta, ranges)); | 508 counts, counts_size, meta, ranges)); |
| 509 logged_samples_.reset(new SampleVector(samples_->id(), logged_counts, |
| 510 counts_size, logged_meta, ranges)); |
489 } | 511 } |
490 } | 512 } |
491 | 513 |
492 Histogram::~Histogram() { | 514 Histogram::~Histogram() { |
493 } | 515 } |
494 | 516 |
495 bool Histogram::PrintEmptyBucket(uint32_t index) const { | 517 bool Histogram::PrintEmptyBucket(uint32_t index) const { |
496 return true; | 518 return true; |
497 } | 519 } |
498 | 520 |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
769 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, | 791 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, |
770 flags); | 792 flags); |
771 } | 793 } |
772 | 794 |
773 HistogramBase* LinearHistogram::PersistentGet( | 795 HistogramBase* LinearHistogram::PersistentGet( |
774 const std::string& name, | 796 const std::string& name, |
775 Sample minimum, | 797 Sample minimum, |
776 Sample maximum, | 798 Sample maximum, |
777 const BucketRanges* ranges, | 799 const BucketRanges* ranges, |
778 HistogramBase::AtomicCount* counts, | 800 HistogramBase::AtomicCount* counts, |
| 801 HistogramBase::AtomicCount* logged_counts, |
779 uint32_t counts_size, | 802 uint32_t counts_size, |
780 HistogramSamples::Metadata* meta) { | 803 HistogramSamples::Metadata* meta, |
| 804 HistogramSamples::Metadata* logged_meta) { |
781 return new LinearHistogram(name, minimum, maximum, ranges, counts, | 805 return new LinearHistogram(name, minimum, maximum, ranges, counts, |
782 counts_size, meta); | 806 logged_counts, counts_size, meta, logged_meta); |
783 } | 807 } |
784 | 808 |
785 HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( | 809 HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( |
786 const std::string& name, | 810 const std::string& name, |
787 Sample minimum, | 811 Sample minimum, |
788 Sample maximum, | 812 Sample maximum, |
789 uint32_t bucket_count, | 813 uint32_t bucket_count, |
790 int32_t flags, | 814 int32_t flags, |
791 const DescriptionPair descriptions[]) { | 815 const DescriptionPair descriptions[]) { |
792 bool valid_arguments = Histogram::InspectConstructionArguments( | 816 bool valid_arguments = Histogram::InspectConstructionArguments( |
(...skipping 13 matching lines...) Expand all Loading... |
806 Sample maximum, | 830 Sample maximum, |
807 const BucketRanges* ranges) | 831 const BucketRanges* ranges) |
808 : Histogram(name, minimum, maximum, ranges) { | 832 : Histogram(name, minimum, maximum, ranges) { |
809 } | 833 } |
810 | 834 |
811 LinearHistogram::LinearHistogram(const std::string& name, | 835 LinearHistogram::LinearHistogram(const std::string& name, |
812 Sample minimum, | 836 Sample minimum, |
813 Sample maximum, | 837 Sample maximum, |
814 const BucketRanges* ranges, | 838 const BucketRanges* ranges, |
815 HistogramBase::AtomicCount* counts, | 839 HistogramBase::AtomicCount* counts, |
| 840 HistogramBase::AtomicCount* logged_counts, |
816 uint32_t counts_size, | 841 uint32_t counts_size, |
817 HistogramSamples::Metadata* meta) | 842 HistogramSamples::Metadata* meta, |
818 : Histogram(name, | 843 HistogramSamples::Metadata* logged_meta) |
819 minimum, | 844 : Histogram(name, minimum, maximum, ranges, counts, logged_counts, |
820 maximum, | 845 counts_size, meta, logged_meta) {} |
821 ranges, | |
822 counts, | |
823 counts_size, | |
824 meta) {} | |
825 | 846 |
826 double LinearHistogram::GetBucketSize(Count current, uint32_t i) const { | 847 double LinearHistogram::GetBucketSize(Count current, uint32_t i) const { |
827 DCHECK_GT(ranges(i + 1), ranges(i)); | 848 DCHECK_GT(ranges(i + 1), ranges(i)); |
828 // Adjacent buckets with different widths would have "surprisingly" many (few) | 849 // Adjacent buckets with different widths would have "surprisingly" many (few) |
829 // samples in a histogram if we didn't normalize this way. | 850 // samples in a histogram if we didn't normalize this way. |
830 double denominator = ranges(i + 1) - ranges(i); | 851 double denominator = ranges(i + 1) - ranges(i); |
831 return current/denominator; | 852 return current/denominator; |
832 } | 853 } |
833 | 854 |
834 const std::string LinearHistogram::GetAsciiBucketRange(uint32_t i) const { | 855 const std::string LinearHistogram::GetAsciiBucketRange(uint32_t i) const { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
912 } | 933 } |
913 | 934 |
914 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32_t flags) { | 935 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32_t flags) { |
915 return FactoryGet(std::string(name), flags); | 936 return FactoryGet(std::string(name), flags); |
916 } | 937 } |
917 | 938 |
918 HistogramBase* BooleanHistogram::PersistentGet( | 939 HistogramBase* BooleanHistogram::PersistentGet( |
919 const std::string& name, | 940 const std::string& name, |
920 const BucketRanges* ranges, | 941 const BucketRanges* ranges, |
921 HistogramBase::AtomicCount* counts, | 942 HistogramBase::AtomicCount* counts, |
922 HistogramSamples::Metadata* meta) { | 943 HistogramBase::AtomicCount* logged_counts, |
923 return new BooleanHistogram(name, ranges, counts, meta); | 944 HistogramSamples::Metadata* meta, |
| 945 HistogramSamples::Metadata* logged_meta) { |
| 946 return new BooleanHistogram(name, ranges, counts, logged_counts, meta, |
| 947 logged_meta); |
924 } | 948 } |
925 | 949 |
926 HistogramType BooleanHistogram::GetHistogramType() const { | 950 HistogramType BooleanHistogram::GetHistogramType() const { |
927 return BOOLEAN_HISTOGRAM; | 951 return BOOLEAN_HISTOGRAM; |
928 } | 952 } |
929 | 953 |
930 BooleanHistogram::BooleanHistogram(const std::string& name, | 954 BooleanHistogram::BooleanHistogram(const std::string& name, |
931 const BucketRanges* ranges) | 955 const BucketRanges* ranges) |
932 : LinearHistogram(name, 1, 2, ranges) {} | 956 : LinearHistogram(name, 1, 2, ranges) {} |
933 | 957 |
934 BooleanHistogram::BooleanHistogram(const std::string& name, | 958 BooleanHistogram::BooleanHistogram(const std::string& name, |
935 const BucketRanges* ranges, | 959 const BucketRanges* ranges, |
936 HistogramBase::AtomicCount* counts, | 960 HistogramBase::AtomicCount* counts, |
937 HistogramSamples::Metadata* meta) | 961 HistogramBase::AtomicCount* logged_counts, |
938 : LinearHistogram(name, 1, 2, ranges, counts, 2, meta) {} | 962 HistogramSamples::Metadata* meta, |
| 963 HistogramSamples::Metadata* logged_meta) |
| 964 : LinearHistogram(name, 1, 2, ranges, counts, logged_counts, 2, meta, |
| 965 logged_meta) {} |
939 | 966 |
940 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { | 967 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { |
941 std::string histogram_name; | 968 std::string histogram_name; |
942 int flags; | 969 int flags; |
943 int declared_min; | 970 int declared_min; |
944 int declared_max; | 971 int declared_max; |
945 uint32_t bucket_count; | 972 uint32_t bucket_count; |
946 uint32_t range_checksum; | 973 uint32_t range_checksum; |
947 | 974 |
948 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, | 975 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1012 const char* name, | 1039 const char* name, |
1013 const std::vector<Sample>& custom_ranges, | 1040 const std::vector<Sample>& custom_ranges, |
1014 int32_t flags) { | 1041 int32_t flags) { |
1015 return FactoryGet(std::string(name), custom_ranges, flags); | 1042 return FactoryGet(std::string(name), custom_ranges, flags); |
1016 } | 1043 } |
1017 | 1044 |
1018 HistogramBase* CustomHistogram::PersistentGet( | 1045 HistogramBase* CustomHistogram::PersistentGet( |
1019 const std::string& name, | 1046 const std::string& name, |
1020 const BucketRanges* ranges, | 1047 const BucketRanges* ranges, |
1021 HistogramBase::AtomicCount* counts, | 1048 HistogramBase::AtomicCount* counts, |
| 1049 HistogramBase::AtomicCount* logged_counts, |
1022 uint32_t counts_size, | 1050 uint32_t counts_size, |
1023 HistogramSamples::Metadata* meta) { | 1051 HistogramSamples::Metadata* meta, |
1024 return new CustomHistogram(name, ranges, counts, counts_size, meta); | 1052 HistogramSamples::Metadata* logged_meta) { |
| 1053 return new CustomHistogram(name, ranges, counts, logged_counts, counts_size, |
| 1054 meta, logged_meta); |
1025 } | 1055 } |
1026 | 1056 |
1027 HistogramType CustomHistogram::GetHistogramType() const { | 1057 HistogramType CustomHistogram::GetHistogramType() const { |
1028 return CUSTOM_HISTOGRAM; | 1058 return CUSTOM_HISTOGRAM; |
1029 } | 1059 } |
1030 | 1060 |
1031 // static | 1061 // static |
1032 std::vector<Sample> CustomHistogram::ArrayToCustomRanges( | 1062 std::vector<Sample> CustomHistogram::ArrayToCustomRanges( |
1033 const Sample* values, uint32_t num_values) { | 1063 const Sample* values, uint32_t num_values) { |
1034 std::vector<Sample> all_values; | 1064 std::vector<Sample> all_values; |
(...skipping 11 matching lines...) Expand all Loading... |
1046 CustomHistogram::CustomHistogram(const std::string& name, | 1076 CustomHistogram::CustomHistogram(const std::string& name, |
1047 const BucketRanges* ranges) | 1077 const BucketRanges* ranges) |
1048 : Histogram(name, | 1078 : Histogram(name, |
1049 ranges->range(1), | 1079 ranges->range(1), |
1050 ranges->range(ranges->bucket_count() - 1), | 1080 ranges->range(ranges->bucket_count() - 1), |
1051 ranges) {} | 1081 ranges) {} |
1052 | 1082 |
1053 CustomHistogram::CustomHistogram(const std::string& name, | 1083 CustomHistogram::CustomHistogram(const std::string& name, |
1054 const BucketRanges* ranges, | 1084 const BucketRanges* ranges, |
1055 HistogramBase::AtomicCount* counts, | 1085 HistogramBase::AtomicCount* counts, |
| 1086 HistogramBase::AtomicCount* logged_counts, |
1056 uint32_t counts_size, | 1087 uint32_t counts_size, |
1057 HistogramSamples::Metadata* meta) | 1088 HistogramSamples::Metadata* meta, |
| 1089 HistogramSamples::Metadata* logged_meta) |
1058 : Histogram(name, | 1090 : Histogram(name, |
1059 ranges->range(1), | 1091 ranges->range(1), |
1060 ranges->range(ranges->bucket_count() - 1), | 1092 ranges->range(ranges->bucket_count() - 1), |
1061 ranges, | 1093 ranges, |
1062 counts, | 1094 counts, |
| 1095 logged_counts, |
1063 counts_size, | 1096 counts_size, |
1064 meta) {} | 1097 meta, |
| 1098 logged_meta) {} |
1065 | 1099 |
1066 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { | 1100 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { |
1067 if (!Histogram::SerializeInfoImpl(pickle)) | 1101 if (!Histogram::SerializeInfoImpl(pickle)) |
1068 return false; | 1102 return false; |
1069 | 1103 |
1070 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't | 1104 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't |
1071 // write them. | 1105 // write them. |
1072 for (uint32_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { | 1106 for (uint32_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { |
1073 if (!pickle->WriteInt(bucket_ranges()->range(i))) | 1107 if (!pickle->WriteInt(bucket_ranges()->range(i))) |
1074 return false; | 1108 return false; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1119 Sample sample = custom_ranges[i]; | 1153 Sample sample = custom_ranges[i]; |
1120 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) | 1154 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) |
1121 return false; | 1155 return false; |
1122 if (sample != 0) | 1156 if (sample != 0) |
1123 has_valid_range = true; | 1157 has_valid_range = true; |
1124 } | 1158 } |
1125 return has_valid_range; | 1159 return has_valid_range; |
1126 } | 1160 } |
1127 | 1161 |
1128 } // namespace base | 1162 } // namespace base |
OLD | NEW |