OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, | 67 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, |
68 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, | 68 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, |
69 0x2d02ef8dL, | 69 0x2d02ef8dL, |
70 }; | 70 }; |
71 | 71 |
72 typedef Histogram::Count Count; | 72 typedef Histogram::Count Count; |
73 | 73 |
74 // static | 74 // static |
75 const size_t Histogram::kBucketCount_MAX = 16384u; | 75 const size_t Histogram::kBucketCount_MAX = 16384u; |
76 | 76 |
| 77 // Collect the number of histograms created. |
| 78 static uint32 number_of_histograms_ = 0; |
| 79 // Collect the number of vectors saved because of caching ranges. |
| 80 static uint32 number_of_vectors_saved_ = 0; |
| 81 // Collect the number of ranges_ elements saved because of caching ranges. |
| 82 static size_t saved_ranges_size_ = 0; |
| 83 |
77 Histogram* Histogram::FactoryGet(const std::string& name, | 84 Histogram* Histogram::FactoryGet(const std::string& name, |
78 Sample minimum, | 85 Sample minimum, |
79 Sample maximum, | 86 Sample maximum, |
80 size_t bucket_count, | 87 size_t bucket_count, |
81 Flags flags) { | 88 Flags flags) { |
82 Histogram* histogram(NULL); | 89 Histogram* histogram(NULL); |
83 | 90 |
84 // Defensive code. | 91 // Defensive code. |
85 if (minimum < 1) | 92 if (minimum < 1) |
86 minimum = 1; | 93 minimum = 1; |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 } | 363 } |
357 } | 364 } |
358 return static_cast<Inconsistencies>(inconsistencies); | 365 return static_cast<Inconsistencies>(inconsistencies); |
359 } | 366 } |
360 | 367 |
361 Histogram::ClassType Histogram::histogram_type() const { | 368 Histogram::ClassType Histogram::histogram_type() const { |
362 return HISTOGRAM; | 369 return HISTOGRAM; |
363 } | 370 } |
364 | 371 |
365 Histogram::Sample Histogram::ranges(size_t i) const { | 372 Histogram::Sample Histogram::ranges(size_t i) const { |
366 return ranges_[i]; | 373 return cached_ranges_->ranges(i); |
367 } | 374 } |
368 | 375 |
369 size_t Histogram::bucket_count() const { | 376 size_t Histogram::bucket_count() const { |
370 return bucket_count_; | 377 return bucket_count_; |
371 } | 378 } |
372 | 379 |
373 // Do a safe atomic snapshot of sample data. | 380 // Do a safe atomic snapshot of sample data. |
374 // This implementation assumes we are on a safe single thread. | 381 // This implementation assumes we are on a safe single thread. |
375 void Histogram::SnapshotSample(SampleSet* sample) const { | 382 void Histogram::SnapshotSample(SampleSet* sample) const { |
376 // Note locking not done in this version!!! | 383 // Note locking not done in this version!!! |
(...skipping 19 matching lines...) Expand all Loading... |
396 return CalculateRangeChecksum() == range_checksum_; | 403 return CalculateRangeChecksum() == range_checksum_; |
397 } | 404 } |
398 | 405 |
399 Histogram::Histogram(const std::string& name, Sample minimum, | 406 Histogram::Histogram(const std::string& name, Sample minimum, |
400 Sample maximum, size_t bucket_count) | 407 Sample maximum, size_t bucket_count) |
401 : histogram_name_(name), | 408 : histogram_name_(name), |
402 declared_min_(minimum), | 409 declared_min_(minimum), |
403 declared_max_(maximum), | 410 declared_max_(maximum), |
404 bucket_count_(bucket_count), | 411 bucket_count_(bucket_count), |
405 flags_(kNoFlags), | 412 flags_(kNoFlags), |
406 ranges_(bucket_count + 1, 0), | 413 cached_ranges_(new CachedRanges(bucket_count + 1, 0)), |
407 range_checksum_(0), | 414 range_checksum_(0), |
408 sample_() { | 415 sample_() { |
409 Initialize(); | 416 Initialize(); |
410 } | 417 } |
411 | 418 |
412 Histogram::Histogram(const std::string& name, TimeDelta minimum, | 419 Histogram::Histogram(const std::string& name, TimeDelta minimum, |
413 TimeDelta maximum, size_t bucket_count) | 420 TimeDelta maximum, size_t bucket_count) |
414 : histogram_name_(name), | 421 : histogram_name_(name), |
415 declared_min_(static_cast<int> (minimum.InMilliseconds())), | 422 declared_min_(static_cast<int> (minimum.InMilliseconds())), |
416 declared_max_(static_cast<int> (maximum.InMilliseconds())), | 423 declared_max_(static_cast<int> (maximum.InMilliseconds())), |
417 bucket_count_(bucket_count), | 424 bucket_count_(bucket_count), |
418 flags_(kNoFlags), | 425 flags_(kNoFlags), |
419 ranges_(bucket_count + 1, 0), | 426 cached_ranges_(new CachedRanges(bucket_count + 1, 0)), |
420 range_checksum_(0), | 427 range_checksum_(0), |
421 sample_() { | 428 sample_() { |
422 Initialize(); | 429 Initialize(); |
423 } | 430 } |
424 | 431 |
425 Histogram::~Histogram() { | 432 Histogram::~Histogram() { |
426 if (StatisticsRecorder::dump_on_exit()) { | 433 if (StatisticsRecorder::dump_on_exit()) { |
427 std::string output; | 434 std::string output; |
428 WriteAscii(true, "\n", &output); | 435 WriteAscii(true, "\n", &output); |
429 LOG(INFO) << output; | 436 LOG(INFO) << output; |
430 } | 437 } |
431 | 438 |
432 // Just to make sure most derived class did this properly... | 439 // Just to make sure most derived class did this properly... |
433 DCHECK(ValidateBucketRanges()); | 440 DCHECK(ValidateBucketRanges()); |
434 } | 441 } |
435 | 442 |
436 // Calculate what range of values are held in each bucket. | 443 // Calculate what range of values are held in each bucket. |
437 // We have to be careful that we don't pick a ratio between starting points in | 444 // We have to be careful that we don't pick a ratio between starting points in |
438 // consecutive buckets that is sooo small, that the integer bounds are the same | 445 // consecutive buckets that is sooo small, that the integer bounds are the same |
439 // (effectively making one bucket get no values). We need to avoid: | 446 // (effectively making one bucket get no values). We need to avoid: |
440 // ranges_[i] == ranges_[i + 1] | 447 // ranges(i) == ranges(i + 1) |
441 // To avoid that, we just do a fine-grained bucket width as far as we need to | 448 // To avoid that, we just do a fine-grained bucket width as far as we need to |
442 // until we get a ratio that moves us along at least 2 units at a time. From | 449 // until we get a ratio that moves us along at least 2 units at a time. From |
443 // that bucket onward we do use the exponential growth of buckets. | 450 // that bucket onward we do use the exponential growth of buckets. |
444 void Histogram::InitializeBucketRange() { | 451 void Histogram::InitializeBucketRange() { |
445 double log_max = log(static_cast<double>(declared_max())); | 452 double log_max = log(static_cast<double>(declared_max())); |
446 double log_ratio; | 453 double log_ratio; |
447 double log_next; | 454 double log_next; |
448 size_t bucket_index = 1; | 455 size_t bucket_index = 1; |
449 Sample current = declared_min(); | 456 Sample current = declared_min(); |
450 SetBucketRange(bucket_index, current); | 457 SetBucketRange(bucket_index, current); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 | 533 |
527 // Update histogram data with new sample. | 534 // Update histogram data with new sample. |
528 void Histogram::Accumulate(Sample value, Count count, size_t index) { | 535 void Histogram::Accumulate(Sample value, Count count, size_t index) { |
529 // Note locking not done in this version!!! | 536 // Note locking not done in this version!!! |
530 sample_.Accumulate(value, count, index); | 537 sample_.Accumulate(value, count, index); |
531 } | 538 } |
532 | 539 |
533 void Histogram::SetBucketRange(size_t i, Sample value) { | 540 void Histogram::SetBucketRange(size_t i, Sample value) { |
534 DCHECK_GT(bucket_count_, i); | 541 DCHECK_GT(bucket_count_, i); |
535 DCHECK_GE(value, 0); | 542 DCHECK_GE(value, 0); |
536 ranges_[i] = value; | 543 cached_ranges_->SetBucketRange(i, value); |
537 } | 544 } |
538 | 545 |
539 bool Histogram::ValidateBucketRanges() const { | 546 bool Histogram::ValidateBucketRanges() const { |
540 // Standard assertions that all bucket ranges should satisfy. | 547 // Standard assertions that all bucket ranges should satisfy. |
541 DCHECK_EQ(bucket_count_ + 1, ranges_.size()); | 548 DCHECK_EQ(bucket_count_ + 1, cached_ranges_->size()); |
542 DCHECK_EQ(0, ranges_[0]); | 549 DCHECK_EQ(0, ranges(0)); |
543 DCHECK_EQ(declared_min(), ranges_[1]); | 550 DCHECK_EQ(declared_min(), ranges(1)); |
544 DCHECK_EQ(declared_max(), ranges_[bucket_count_ - 1]); | 551 DCHECK_EQ(declared_max(), ranges(bucket_count_ - 1)); |
545 DCHECK_EQ(kSampleType_MAX, ranges_[bucket_count_]); | 552 DCHECK_EQ(kSampleType_MAX, ranges(bucket_count_)); |
546 return true; | 553 return true; |
547 } | 554 } |
548 | 555 |
549 uint32 Histogram::CalculateRangeChecksum() const { | 556 uint32 Histogram::CalculateRangeChecksum() const { |
550 DCHECK_EQ(ranges_.size(), bucket_count() + 1); | 557 DCHECK_EQ(cached_ranges_->size(), bucket_count() + 1); |
551 uint32 checksum = static_cast<uint32>(ranges_.size()); // Seed checksum. | 558 // Seed checksum. |
| 559 uint32 checksum = static_cast<uint32>(cached_ranges_->size()); |
552 for (size_t index = 0; index < bucket_count(); ++index) | 560 for (size_t index = 0; index < bucket_count(); ++index) |
553 checksum = Crc32(checksum, ranges(index)); | 561 checksum = Crc32(checksum, ranges(index)); |
554 return checksum; | 562 return checksum; |
555 } | 563 } |
556 | 564 |
557 void Histogram::Initialize() { | 565 void Histogram::Initialize() { |
558 sample_.Resize(*this); | 566 sample_.Resize(*this); |
559 if (declared_min_ < 1) | 567 if (declared_min_ < 1) |
560 declared_min_ = 1; | 568 declared_min_ = 1; |
561 if (declared_max_ > kSampleType_MAX - 1) | 569 if (declared_max_ > kSampleType_MAX - 1) |
562 declared_max_ = kSampleType_MAX - 1; | 570 declared_max_ = kSampleType_MAX - 1; |
563 DCHECK_LE(declared_min_, declared_max_); | 571 DCHECK_LE(declared_min_, declared_max_); |
564 DCHECK_GT(bucket_count_, 1u); | 572 DCHECK_GT(bucket_count_, 1u); |
565 CHECK_LT(bucket_count_, kBucketCount_MAX); | 573 CHECK_LT(bucket_count_, kBucketCount_MAX); |
566 size_t maximal_bucket_count = declared_max_ - declared_min_ + 2; | 574 size_t maximal_bucket_count = declared_max_ - declared_min_ + 2; |
567 DCHECK_LE(bucket_count_, maximal_bucket_count); | 575 DCHECK_LE(bucket_count_, maximal_bucket_count); |
568 DCHECK_EQ(0, ranges_[0]); | 576 DCHECK_EQ(0, ranges(0)); |
569 ranges_[bucket_count_] = kSampleType_MAX; | 577 cached_ranges_->SetBucketRange(bucket_count_, kSampleType_MAX); |
570 } | 578 } |
571 | 579 |
572 // We generate the CRC-32 using the low order bits to select whether to XOR in | 580 // We generate the CRC-32 using the low order bits to select whether to XOR in |
573 // the reversed polynomial 0xedb88320L. This is nice and simple, and allows us | 581 // the reversed polynomial 0xedb88320L. This is nice and simple, and allows us |
574 // to keep the quotient in a uint32. Since we're not concerned about the nature | 582 // to keep the quotient in a uint32. Since we're not concerned about the nature |
575 // of corruptions (i.e., we don't care about bit sequencing, since we are | 583 // of corruptions (i.e., we don't care about bit sequencing, since we are |
576 // handling memory changes, which are more grotesque) so we don't bother to | 584 // handling memory changes, which are more grotesque) so we don't bother to |
577 // get the CRC correct for big-endian vs little-ending calculations. All we | 585 // get the CRC correct for big-endian vs little-ending calculations. All we |
578 // need is a nice hash, that tends to depend on all the bits of the sample, with | 586 // need is a nice hash, that tends to depend on all the bits of the sample, with |
579 // very little chance of changes in one place impacting changes in another | 587 // very little chance of changes in one place impacting changes in another |
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1001 // This will leak on purpose. It's the only way to make sure we won't race | 1009 // This will leak on purpose. It's the only way to make sure we won't race |
1002 // against the static uninitialization of the module while one of our | 1010 // against the static uninitialization of the module while one of our |
1003 // static methods relying on the lock get called at an inappropriate time | 1011 // static methods relying on the lock get called at an inappropriate time |
1004 // during the termination phase. Since it's a static data member, we will | 1012 // during the termination phase. Since it's a static data member, we will |
1005 // leak one per process, which would be similar to the instance allocated | 1013 // leak one per process, which would be similar to the instance allocated |
1006 // during static initialization and released only on process termination. | 1014 // during static initialization and released only on process termination. |
1007 lock_ = new base::Lock; | 1015 lock_ = new base::Lock; |
1008 } | 1016 } |
1009 base::AutoLock auto_lock(*lock_); | 1017 base::AutoLock auto_lock(*lock_); |
1010 histograms_ = new HistogramMap; | 1018 histograms_ = new HistogramMap; |
| 1019 ranges_ = new RangesMap; |
1011 } | 1020 } |
1012 | 1021 |
1013 StatisticsRecorder::~StatisticsRecorder() { | 1022 StatisticsRecorder::~StatisticsRecorder() { |
1014 DCHECK(histograms_ && lock_); | 1023 DCHECK(histograms_ && lock_); |
1015 | 1024 |
1016 if (dump_on_exit_) { | 1025 if (dump_on_exit_) { |
1017 std::string output; | 1026 std::string output; |
1018 WriteGraph("", &output); | 1027 WriteGraph("", &output); |
1019 LOG(INFO) << output; | 1028 LOG(INFO) << output; |
1020 } | 1029 } |
1021 // Clean up. | 1030 // Clean up. |
1022 HistogramMap* histograms = NULL; | 1031 HistogramMap* histograms = NULL; |
1023 { | 1032 { |
1024 base::AutoLock auto_lock(*lock_); | 1033 base::AutoLock auto_lock(*lock_); |
1025 histograms = histograms_; | 1034 histograms = histograms_; |
1026 histograms_ = NULL; | 1035 histograms_ = NULL; |
1027 } | 1036 } |
| 1037 RangesMap* ranges = NULL; |
| 1038 { |
| 1039 base::AutoLock auto_lock(*lock_); |
| 1040 ranges = ranges_; |
| 1041 ranges_ = NULL; |
| 1042 } |
| 1043 // We are going to leak the histograms and the ranges. |
1028 delete histograms; | 1044 delete histograms; |
| 1045 delete ranges; |
1029 // We don't delete lock_ on purpose to avoid having to properly protect | 1046 // We don't delete lock_ on purpose to avoid having to properly protect |
1030 // against it going away after we checked for NULL in the static methods. | 1047 // against it going away after we checked for NULL in the static methods. |
1031 } | 1048 } |
1032 | 1049 |
1033 // static | 1050 // static |
1034 bool StatisticsRecorder::IsActive() { | 1051 bool StatisticsRecorder::IsActive() { |
1035 if (lock_ == NULL) | 1052 if (lock_ == NULL) |
1036 return false; | 1053 return false; |
1037 base::AutoLock auto_lock(*lock_); | 1054 base::AutoLock auto_lock(*lock_); |
1038 return NULL != histograms_; | 1055 return NULL != histograms_; |
(...skipping 14 matching lines...) Expand all Loading... |
1053 if (!histograms_) { | 1070 if (!histograms_) { |
1054 ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 | 1071 ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 |
1055 return histogram; | 1072 return histogram; |
1056 } | 1073 } |
1057 const std::string name = histogram->histogram_name(); | 1074 const std::string name = histogram->histogram_name(); |
1058 HistogramMap::iterator it = histograms_->find(name); | 1075 HistogramMap::iterator it = histograms_->find(name); |
1059 // Avoid overwriting a previous registration. | 1076 // Avoid overwriting a previous registration. |
1060 if (histograms_->end() == it) { | 1077 if (histograms_->end() == it) { |
1061 (*histograms_)[name] = histogram; | 1078 (*histograms_)[name] = histogram; |
1062 ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 | 1079 ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 |
| 1080 RegisterOrDeleteDuplicateRanges(histogram); |
| 1081 ++number_of_histograms_; |
1063 } else { | 1082 } else { |
1064 delete histogram; // We already have one by this name. | 1083 delete histogram; // We already have one by this name. |
1065 histogram = it->second; | 1084 histogram = it->second; |
1066 } | 1085 } |
1067 return histogram; | 1086 return histogram; |
1068 } | 1087 } |
1069 | 1088 |
1070 // static | 1089 // static |
| 1090 void StatisticsRecorder::RegisterOrDeleteDuplicateRanges(Histogram* histogram) { |
| 1091 DCHECK(histogram); |
| 1092 CachedRanges* histogram_ranges = histogram->cached_ranges(); |
| 1093 DCHECK(histogram_ranges); |
| 1094 uint32 checksum = histogram->range_checksum(); |
| 1095 histogram_ranges->SetRangeChecksum(checksum); |
| 1096 |
| 1097 RangesMap::iterator ranges_it = ranges_->find(checksum); |
| 1098 if (ranges_->end() == ranges_it) { |
| 1099 // Register the new CachedRanges. |
| 1100 std::list<CachedRanges*>* checksum_matching_list( |
| 1101 new std::list<CachedRanges*>()); |
| 1102 checksum_matching_list->push_front(histogram_ranges); |
| 1103 (*ranges_)[checksum] = checksum_matching_list; |
| 1104 return; |
| 1105 } |
| 1106 |
| 1107 // Use the registered CachedRanges if the registered CachedRanges has same |
| 1108 // ranges_ as |histogram|'s CachedRanges. |
| 1109 std::list<CachedRanges*>* checksum_matching_list = ranges_it->second; |
| 1110 std::list<CachedRanges*>::iterator checksum_matching_list_it; |
| 1111 for (checksum_matching_list_it = checksum_matching_list->begin(); |
| 1112 checksum_matching_list_it != checksum_matching_list->end(); |
| 1113 ++checksum_matching_list_it) { |
| 1114 CachedRanges* existing_histogram_ranges = *checksum_matching_list_it; |
| 1115 DCHECK(existing_histogram_ranges); |
| 1116 if (existing_histogram_ranges->Equals(histogram_ranges)) { |
| 1117 histogram->set_cached_ranges(existing_histogram_ranges); |
| 1118 ++number_of_vectors_saved_; |
| 1119 saved_ranges_size_ += histogram_ranges->size(); |
| 1120 delete histogram_ranges; |
| 1121 return; |
| 1122 } |
| 1123 } |
| 1124 |
| 1125 // We haven't found a CachedRanges which has the same ranges. Register the |
| 1126 // new CachedRanges. |
| 1127 DCHECK(checksum_matching_list_it == checksum_matching_list->end()); |
| 1128 checksum_matching_list->push_front(histogram_ranges); |
| 1129 } |
| 1130 |
| 1131 // static |
| 1132 void StatisticsRecorder::CollectHistogramStats(const std::string& suffix) { |
| 1133 static int uma_upload_attempt = 0; |
| 1134 ++uma_upload_attempt; |
| 1135 if (uma_upload_attempt == 1) { |
| 1136 UMA_HISTOGRAM_COUNTS_10000( |
| 1137 "Histogram.SharedRange.Count.FirstUpload." + suffix, |
| 1138 number_of_histograms_); |
| 1139 UMA_HISTOGRAM_COUNTS_10000( |
| 1140 "Histogram.SharedRange.RangesSaved.FirstUpload." + suffix, |
| 1141 number_of_vectors_saved_); |
| 1142 UMA_HISTOGRAM_COUNTS( |
| 1143 "Histogram.SharedRange.ElementsSaved.FirstUpload." + suffix, |
| 1144 static_cast<int>(saved_ranges_size_)); |
| 1145 number_of_histograms_ = 0; |
| 1146 number_of_vectors_saved_ = 0; |
| 1147 saved_ranges_size_ = 0; |
| 1148 return; |
| 1149 } |
| 1150 if (uma_upload_attempt == 2) { |
| 1151 UMA_HISTOGRAM_COUNTS_10000( |
| 1152 "Histogram.SharedRange.Count.SecondUpload." + suffix, |
| 1153 number_of_histograms_); |
| 1154 UMA_HISTOGRAM_COUNTS_10000( |
| 1155 "Histogram.SharedRange.RangesSaved.SecondUpload." + suffix, |
| 1156 number_of_vectors_saved_); |
| 1157 UMA_HISTOGRAM_COUNTS( |
| 1158 "Histogram.SharedRange.ElementsSaved.SecondUpload." + suffix, |
| 1159 static_cast<int>(saved_ranges_size_)); |
| 1160 number_of_histograms_ = 0; |
| 1161 number_of_vectors_saved_ = 0; |
| 1162 saved_ranges_size_ = 0; |
| 1163 return; |
| 1164 } |
| 1165 UMA_HISTOGRAM_COUNTS_10000( |
| 1166 "Histogram.SharedRange.Count.RestOfUploads." + suffix, |
| 1167 number_of_histograms_); |
| 1168 UMA_HISTOGRAM_COUNTS_10000( |
| 1169 "Histogram.SharedRange.RangesSaved.RestOfUploads." + suffix, |
| 1170 number_of_vectors_saved_); |
| 1171 UMA_HISTOGRAM_COUNTS( |
| 1172 "Histogram.SharedRange.ElementsSaved.RestOfUploads." + suffix, |
| 1173 static_cast<int>(saved_ranges_size_)); |
| 1174 } |
| 1175 |
| 1176 // static |
1071 void StatisticsRecorder::WriteHTMLGraph(const std::string& query, | 1177 void StatisticsRecorder::WriteHTMLGraph(const std::string& query, |
1072 std::string* output) { | 1178 std::string* output) { |
1073 if (!IsActive()) | 1179 if (!IsActive()) |
1074 return; | 1180 return; |
1075 | 1181 |
1076 Histograms snapshot; | 1182 Histograms snapshot; |
1077 GetSnapshot(query, &snapshot); | 1183 GetSnapshot(query, &snapshot); |
1078 for (Histograms::iterator it = snapshot.begin(); | 1184 for (Histograms::iterator it = snapshot.begin(); |
1079 it != snapshot.end(); | 1185 it != snapshot.end(); |
1080 ++it) { | 1186 ++it) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1141 if (!histograms_) | 1247 if (!histograms_) |
1142 return; | 1248 return; |
1143 for (HistogramMap::iterator it = histograms_->begin(); | 1249 for (HistogramMap::iterator it = histograms_->begin(); |
1144 histograms_->end() != it; | 1250 histograms_->end() != it; |
1145 ++it) { | 1251 ++it) { |
1146 if (it->first.find(query) != std::string::npos) | 1252 if (it->first.find(query) != std::string::npos) |
1147 snapshot->push_back(it->second); | 1253 snapshot->push_back(it->second); |
1148 } | 1254 } |
1149 } | 1255 } |
1150 | 1256 |
| 1257 CachedRanges::CachedRanges(size_t bucket_count, int initial_value) |
| 1258 : ranges_(bucket_count, initial_value), |
| 1259 range_checksum_(0) { |
| 1260 } |
| 1261 |
| 1262 CachedRanges::~CachedRanges() { |
| 1263 } |
| 1264 |
| 1265 void CachedRanges::SetBucketRange(size_t i, Histogram::Sample value) { |
| 1266 DCHECK_LT(i, ranges_.size()); |
| 1267 DCHECK_GE(value, 0); |
| 1268 ranges_[i] = value; |
| 1269 } |
| 1270 |
| 1271 bool CachedRanges::Equals(CachedRanges* other) const { |
| 1272 if (range_checksum_ != other->range_checksum_) |
| 1273 return false; |
| 1274 if (ranges_.size() != other->ranges_.size()) |
| 1275 return false; |
| 1276 for (size_t index = 0; index < ranges_.size(); ++index) { |
| 1277 if (ranges_[index] != other->ranges_[index]) |
| 1278 return false; |
| 1279 } |
| 1280 return true; |
| 1281 } |
| 1282 |
1151 // static | 1283 // static |
1152 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; | 1284 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; |
1153 // static | 1285 // static |
| 1286 StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL; |
| 1287 // static |
1154 base::Lock* StatisticsRecorder::lock_ = NULL; | 1288 base::Lock* StatisticsRecorder::lock_ = NULL; |
1155 // static | 1289 // static |
1156 bool StatisticsRecorder::dump_on_exit_ = false; | 1290 bool StatisticsRecorder::dump_on_exit_ = false; |
1157 | |
1158 } // namespace base | 1291 } // namespace base |
OLD | NEW |