| 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 |