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 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
348 } | 355 } |
349 } | 356 } |
350 return static_cast<Inconsistencies>(inconsistencies); | 357 return static_cast<Inconsistencies>(inconsistencies); |
351 } | 358 } |
352 | 359 |
353 Histogram::ClassType Histogram::histogram_type() const { | 360 Histogram::ClassType Histogram::histogram_type() const { |
354 return HISTOGRAM; | 361 return HISTOGRAM; |
355 } | 362 } |
356 | 363 |
357 Histogram::Sample Histogram::ranges(size_t i) const { | 364 Histogram::Sample Histogram::ranges(size_t i) const { |
358 return ranges_[i]; | 365 return cached_ranges_->ranges(i); |
359 } | 366 } |
360 | 367 |
361 size_t Histogram::bucket_count() const { | 368 size_t Histogram::bucket_count() const { |
362 return bucket_count_; | 369 return bucket_count_; |
363 } | 370 } |
364 | 371 |
365 // Do a safe atomic snapshot of sample data. | 372 // Do a safe atomic snapshot of sample data. |
366 // This implementation assumes we are on a safe single thread. | 373 // This implementation assumes we are on a safe single thread. |
367 void Histogram::SnapshotSample(SampleSet* sample) const { | 374 void Histogram::SnapshotSample(SampleSet* sample) const { |
368 // Note locking not done in this version!!! | 375 // Note locking not done in this version!!! |
(...skipping 19 matching lines...) Expand all Loading... | |
388 return CalculateRangeChecksum() == range_checksum_; | 395 return CalculateRangeChecksum() == range_checksum_; |
389 } | 396 } |
390 | 397 |
391 Histogram::Histogram(const std::string& name, Sample minimum, | 398 Histogram::Histogram(const std::string& name, Sample minimum, |
392 Sample maximum, size_t bucket_count) | 399 Sample maximum, size_t bucket_count) |
393 : histogram_name_(name), | 400 : histogram_name_(name), |
394 declared_min_(minimum), | 401 declared_min_(minimum), |
395 declared_max_(maximum), | 402 declared_max_(maximum), |
396 bucket_count_(bucket_count), | 403 bucket_count_(bucket_count), |
397 flags_(kNoFlags), | 404 flags_(kNoFlags), |
398 ranges_(bucket_count + 1, 0), | 405 cached_ranges_(new CachedRanges(bucket_count + 1, 0)), |
399 range_checksum_(0), | 406 range_checksum_(0), |
400 sample_() { | 407 sample_() { |
401 Initialize(); | 408 Initialize(); |
402 } | 409 } |
403 | 410 |
404 Histogram::Histogram(const std::string& name, TimeDelta minimum, | 411 Histogram::Histogram(const std::string& name, TimeDelta minimum, |
405 TimeDelta maximum, size_t bucket_count) | 412 TimeDelta maximum, size_t bucket_count) |
406 : histogram_name_(name), | 413 : histogram_name_(name), |
407 declared_min_(static_cast<int> (minimum.InMilliseconds())), | 414 declared_min_(static_cast<int> (minimum.InMilliseconds())), |
408 declared_max_(static_cast<int> (maximum.InMilliseconds())), | 415 declared_max_(static_cast<int> (maximum.InMilliseconds())), |
409 bucket_count_(bucket_count), | 416 bucket_count_(bucket_count), |
410 flags_(kNoFlags), | 417 flags_(kNoFlags), |
411 ranges_(bucket_count + 1, 0), | 418 cached_ranges_(new CachedRanges(bucket_count + 1, 0)), |
412 range_checksum_(0), | 419 range_checksum_(0), |
413 sample_() { | 420 sample_() { |
414 Initialize(); | 421 Initialize(); |
415 } | 422 } |
416 | 423 |
417 Histogram::~Histogram() { | 424 Histogram::~Histogram() { |
418 if (StatisticsRecorder::dump_on_exit()) { | 425 if (StatisticsRecorder::dump_on_exit()) { |
419 std::string output; | 426 std::string output; |
420 WriteAscii(true, "\n", &output); | 427 WriteAscii(true, "\n", &output); |
421 LOG(INFO) << output; | 428 LOG(INFO) << output; |
422 } | 429 } |
423 | 430 |
424 // Just to make sure most derived class did this properly... | 431 // Just to make sure most derived class did this properly... |
425 DCHECK(ValidateBucketRanges()); | 432 DCHECK(ValidateBucketRanges()); |
426 } | 433 } |
427 | 434 |
428 // Calculate what range of values are held in each bucket. | 435 // Calculate what range of values are held in each bucket. |
429 // We have to be careful that we don't pick a ratio between starting points in | 436 // We have to be careful that we don't pick a ratio between starting points in |
430 // consecutive buckets that is sooo small, that the integer bounds are the same | 437 // consecutive buckets that is sooo small, that the integer bounds are the same |
431 // (effectively making one bucket get no values). We need to avoid: | 438 // (effectively making one bucket get no values). We need to avoid: |
432 // ranges_[i] == ranges_[i + 1] | 439 // ranges(i) == ranges(i + 1) |
433 // To avoid that, we just do a fine-grained bucket width as far as we need to | 440 // To avoid that, we just do a fine-grained bucket width as far as we need to |
434 // until we get a ratio that moves us along at least 2 units at a time. From | 441 // until we get a ratio that moves us along at least 2 units at a time. From |
435 // that bucket onward we do use the exponential growth of buckets. | 442 // that bucket onward we do use the exponential growth of buckets. |
436 void Histogram::InitializeBucketRange() { | 443 void Histogram::InitializeBucketRange() { |
437 double log_max = log(static_cast<double>(declared_max())); | 444 double log_max = log(static_cast<double>(declared_max())); |
438 double log_ratio; | 445 double log_ratio; |
439 double log_next; | 446 double log_next; |
440 size_t bucket_index = 1; | 447 size_t bucket_index = 1; |
441 Sample current = declared_min(); | 448 Sample current = declared_min(); |
442 SetBucketRange(bucket_index, current); | 449 SetBucketRange(bucket_index, current); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
518 | 525 |
519 // Update histogram data with new sample. | 526 // Update histogram data with new sample. |
520 void Histogram::Accumulate(Sample value, Count count, size_t index) { | 527 void Histogram::Accumulate(Sample value, Count count, size_t index) { |
521 // Note locking not done in this version!!! | 528 // Note locking not done in this version!!! |
522 sample_.Accumulate(value, count, index); | 529 sample_.Accumulate(value, count, index); |
523 } | 530 } |
524 | 531 |
525 void Histogram::SetBucketRange(size_t i, Sample value) { | 532 void Histogram::SetBucketRange(size_t i, Sample value) { |
526 DCHECK_GT(bucket_count_, i); | 533 DCHECK_GT(bucket_count_, i); |
527 DCHECK_GE(value, 0); | 534 DCHECK_GE(value, 0); |
528 ranges_[i] = value; | 535 cached_ranges_->SetBucketRange(i, value); |
529 } | 536 } |
530 | 537 |
531 bool Histogram::ValidateBucketRanges() const { | 538 bool Histogram::ValidateBucketRanges() const { |
532 // Standard assertions that all bucket ranges should satisfy. | 539 // Standard assertions that all bucket ranges should satisfy. |
533 DCHECK_EQ(bucket_count_ + 1, ranges_.size()); | 540 DCHECK_EQ(bucket_count_ + 1, cached_ranges_->size()); |
534 DCHECK_EQ(0, ranges_[0]); | 541 DCHECK_EQ(0, ranges(0)); |
535 DCHECK_EQ(declared_min(), ranges_[1]); | 542 DCHECK_EQ(declared_min(), ranges(1)); |
536 DCHECK_EQ(declared_max(), ranges_[bucket_count_ - 1]); | 543 DCHECK_EQ(declared_max(), ranges(bucket_count_ - 1)); |
537 DCHECK_EQ(kSampleType_MAX, ranges_[bucket_count_]); | 544 DCHECK_EQ(kSampleType_MAX, ranges(bucket_count_)); |
538 return true; | 545 return true; |
539 } | 546 } |
540 | 547 |
541 uint32 Histogram::CalculateRangeChecksum() const { | 548 uint32 Histogram::CalculateRangeChecksum() const { |
542 DCHECK_EQ(ranges_.size(), bucket_count() + 1); | 549 DCHECK_EQ(cached_ranges_->size(), bucket_count() + 1); |
543 uint32 checksum = static_cast<uint32>(ranges_.size()); // Seed checksum. | 550 // Seed checksum. |
551 uint32 checksum = static_cast<uint32>(cached_ranges_->size()); | |
544 for (size_t index = 0; index < bucket_count(); ++index) | 552 for (size_t index = 0; index < bucket_count(); ++index) |
545 checksum = Crc32(checksum, ranges(index)); | 553 checksum = Crc32(checksum, ranges(index)); |
546 return checksum; | 554 return checksum; |
547 } | 555 } |
548 | 556 |
549 void Histogram::Initialize() { | 557 void Histogram::Initialize() { |
550 sample_.Resize(*this); | 558 sample_.Resize(*this); |
551 if (declared_min_ < 1) | 559 if (declared_min_ < 1) |
552 declared_min_ = 1; | 560 declared_min_ = 1; |
553 if (declared_max_ > kSampleType_MAX - 1) | 561 if (declared_max_ > kSampleType_MAX - 1) |
554 declared_max_ = kSampleType_MAX - 1; | 562 declared_max_ = kSampleType_MAX - 1; |
555 DCHECK_LE(declared_min_, declared_max_); | 563 DCHECK_LE(declared_min_, declared_max_); |
556 DCHECK_GT(bucket_count_, 1u); | 564 DCHECK_GT(bucket_count_, 1u); |
557 CHECK_LT(bucket_count_, kBucketCount_MAX); | 565 CHECK_LT(bucket_count_, kBucketCount_MAX); |
558 size_t maximal_bucket_count = declared_max_ - declared_min_ + 2; | 566 size_t maximal_bucket_count = declared_max_ - declared_min_ + 2; |
559 DCHECK_LE(bucket_count_, maximal_bucket_count); | 567 DCHECK_LE(bucket_count_, maximal_bucket_count); |
560 DCHECK_EQ(0, ranges_[0]); | 568 DCHECK_EQ(0, ranges(0)); |
561 ranges_[bucket_count_] = kSampleType_MAX; | 569 cached_ranges_->SetBucketRange(bucket_count_, kSampleType_MAX); |
562 } | 570 } |
563 | 571 |
564 // We generate the CRC-32 using the low order bits to select whether to XOR in | 572 // We generate the CRC-32 using the low order bits to select whether to XOR in |
565 // the reversed polynomial 0xedb88320L. This is nice and simple, and allows us | 573 // the reversed polynomial 0xedb88320L. This is nice and simple, and allows us |
566 // to keep the quotient in a uint32. Since we're not concerned about the nature | 574 // to keep the quotient in a uint32. Since we're not concerned about the nature |
567 // of corruptions (i.e., we don't care about bit sequencing, since we are | 575 // of corruptions (i.e., we don't care about bit sequencing, since we are |
568 // handling memory changes, which are more grotesque) so we don't bother to | 576 // handling memory changes, which are more grotesque) so we don't bother to |
569 // get the CRC correct for big-endian vs little-ending calculations. All we | 577 // get the CRC correct for big-endian vs little-ending calculations. All we |
570 // need is a nice hash, that tends to depend on all the bits of the sample, with | 578 // need is a nice hash, that tends to depend on all the bits of the sample, with |
571 // very little chance of changes in one place impacting changes in another | 579 // 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... | |
993 // This will leak on purpose. It's the only way to make sure we won't race | 1001 // This will leak on purpose. It's the only way to make sure we won't race |
994 // against the static uninitialization of the module while one of our | 1002 // against the static uninitialization of the module while one of our |
995 // static methods relying on the lock get called at an inappropriate time | 1003 // static methods relying on the lock get called at an inappropriate time |
996 // during the termination phase. Since it's a static data member, we will | 1004 // during the termination phase. Since it's a static data member, we will |
997 // leak one per process, which would be similar to the instance allocated | 1005 // leak one per process, which would be similar to the instance allocated |
998 // during static initialization and released only on process termination. | 1006 // during static initialization and released only on process termination. |
999 lock_ = new base::Lock; | 1007 lock_ = new base::Lock; |
1000 } | 1008 } |
1001 base::AutoLock auto_lock(*lock_); | 1009 base::AutoLock auto_lock(*lock_); |
1002 histograms_ = new HistogramMap; | 1010 histograms_ = new HistogramMap; |
1011 ranges_ = new RangesMap; | |
1003 } | 1012 } |
1004 | 1013 |
1005 StatisticsRecorder::~StatisticsRecorder() { | 1014 StatisticsRecorder::~StatisticsRecorder() { |
1006 DCHECK(histograms_ && lock_); | 1015 DCHECK(histograms_ && lock_); |
1007 | 1016 |
1008 if (dump_on_exit_) { | 1017 if (dump_on_exit_) { |
1009 std::string output; | 1018 std::string output; |
1010 WriteGraph("", &output); | 1019 WriteGraph("", &output); |
1011 LOG(INFO) << output; | 1020 LOG(INFO) << output; |
1012 } | 1021 } |
1013 // Clean up. | 1022 // Clean up. |
1014 HistogramMap* histograms = NULL; | 1023 HistogramMap* histograms = NULL; |
1015 { | 1024 { |
1016 base::AutoLock auto_lock(*lock_); | 1025 base::AutoLock auto_lock(*lock_); |
1017 histograms = histograms_; | 1026 histograms = histograms_; |
1018 histograms_ = NULL; | 1027 histograms_ = NULL; |
1019 } | 1028 } |
1020 delete histograms; | 1029 delete histograms; |
1030 RangesMap* ranges = NULL; | |
1031 { | |
1032 base::AutoLock auto_lock(*lock_); | |
1033 ranges = ranges_; | |
1034 ranges_ = NULL; | |
1035 } | |
1036 delete ranges; | |
jar (doing other things)
2011/10/04 22:32:38
I'd suggest we explicity comment that we are going
ramant (doing other things)
2011/10/19 01:09:52
Done.
| |
1021 // We don't delete lock_ on purpose to avoid having to properly protect | 1037 // We don't delete lock_ on purpose to avoid having to properly protect |
1022 // against it going away after we checked for NULL in the static methods. | 1038 // against it going away after we checked for NULL in the static methods. |
1023 } | 1039 } |
1024 | 1040 |
1025 // static | 1041 // static |
1026 bool StatisticsRecorder::IsActive() { | 1042 bool StatisticsRecorder::IsActive() { |
1027 if (lock_ == NULL) | 1043 if (lock_ == NULL) |
1028 return false; | 1044 return false; |
1029 base::AutoLock auto_lock(*lock_); | 1045 base::AutoLock auto_lock(*lock_); |
1030 return NULL != histograms_; | 1046 return NULL != histograms_; |
(...skipping 14 matching lines...) Expand all Loading... | |
1045 if (!histograms_) { | 1061 if (!histograms_) { |
1046 ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 | 1062 ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 |
1047 return histogram; | 1063 return histogram; |
1048 } | 1064 } |
1049 const std::string name = histogram->histogram_name(); | 1065 const std::string name = histogram->histogram_name(); |
1050 HistogramMap::iterator it = histograms_->find(name); | 1066 HistogramMap::iterator it = histograms_->find(name); |
1051 // Avoid overwriting a previous registration. | 1067 // Avoid overwriting a previous registration. |
1052 if (histograms_->end() == it) { | 1068 if (histograms_->end() == it) { |
1053 (*histograms_)[name] = histogram; | 1069 (*histograms_)[name] = histogram; |
1054 ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 | 1070 ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 |
1071 RegisterOrDeleteDuplicateRanges(histogram); | |
1072 ++number_of_histograms_; | |
1055 } else { | 1073 } else { |
1056 delete histogram; // We already have one by this name. | 1074 delete histogram; // We already have one by this name. |
1057 histogram = it->second; | 1075 histogram = it->second; |
1058 } | 1076 } |
1059 return histogram; | 1077 return histogram; |
1060 } | 1078 } |
1061 | 1079 |
1062 // static | 1080 // static |
1081 void StatisticsRecorder::RegisterOrDeleteDuplicateRanges(Histogram* histogram) { | |
1082 DCHECK(histogram); | |
1083 CachedRanges* cached_ranges = histogram->cached_ranges(); | |
jar (doing other things)
2011/10/04 22:32:38
nit: suggest name change for the local variable he
ramant (doing other things)
2011/10/19 01:09:52
Done.
| |
1084 DCHECK(cached_ranges); | |
1085 uint32 checksum = histogram->range_checksum(); | |
1086 cached_ranges->SetRangeChecksum(checksum); | |
1087 | |
1088 RangesMap::iterator ranges_it = ranges_->find(checksum); | |
1089 if (ranges_->end() == ranges_it) { | |
1090 // Register the new CachedRanges. | |
1091 std::list<CachedRanges*>* ranges_list(new std::list<CachedRanges*>()); | |
jar (doing other things)
2011/10/04 22:32:38
nit: suggest name change for local variable:
rang
ramant (doing other things)
2011/10/19 01:09:52
Done.
| |
1092 ranges_list->push_front(cached_ranges); | |
1093 (*ranges_)[checksum] = ranges_list; | |
1094 return; | |
1095 } | |
1096 | |
1097 // Use the registered CachedRanges if the registered CachedRanges has same | |
1098 // ranges_ as |histogram|'s CachedRanges. | |
1099 std::list<CachedRanges*>* ranges_list = ranges_it->second; | |
1100 std::list<CachedRanges*>::iterator ranges_list_it; | |
1101 for (ranges_list_it = ranges_list->begin(); | |
1102 ranges_list_it != ranges_list->end(); | |
1103 ++ranges_list_it) { | |
1104 CachedRanges* existing_cached_ranges = *ranges_list_it; | |
1105 DCHECK(existing_cached_ranges); | |
1106 if (existing_cached_ranges->Equals(cached_ranges)) { | |
1107 histogram->set_cached_ranges(existing_cached_ranges); | |
1108 ++number_of_vectors_saved_; | |
1109 saved_ranges_size_ += cached_ranges->size(); | |
1110 delete cached_ranges; | |
1111 return; | |
1112 } | |
1113 } | |
1114 | |
1115 // We haven't found a CachedRanges which has the same ranges. Register the | |
1116 // new CachedRanges. | |
1117 DCHECK(ranges_list_it == ranges_list->end()); | |
1118 ranges_list->push_front(cached_ranges); | |
1119 } | |
1120 | |
1121 // static | |
1122 void StatisticsRecorder::CollectHistogramStats(const std::string& suffix) { | |
1123 static int uma_upload_attempt = 0; | |
1124 ++uma_upload_attempt; | |
1125 if (uma_upload_attempt == 1) { | |
1126 UMA_HISTOGRAM_COUNTS_10000("Histogram.FirstUpload.Count." + suffix, | |
jar (doing other things)
2011/10/04 22:32:38
For histogram naming, it is always nice to have si
ramant (doing other things)
2011/10/19 01:09:52
Done.
| |
1127 number_of_histograms_); | |
1128 UMA_HISTOGRAM_COUNTS_10000("Histogram.FirstUpload.RangesSaved." + suffix, | |
1129 number_of_vectors_saved_); | |
1130 UMA_HISTOGRAM_COUNTS("Histogram.FirstUpload.RangesElementsSaved." + suffix, | |
1131 static_cast<int>(saved_ranges_size_)); | |
1132 number_of_histograms_ = 0; | |
1133 number_of_vectors_saved_ = 0; | |
1134 saved_ranges_size_ = 0; | |
1135 return; | |
1136 } | |
1137 if (uma_upload_attempt == 2) { | |
1138 UMA_HISTOGRAM_COUNTS_10000("Histogram.SecondUpload.Count." + suffix, | |
1139 number_of_histograms_); | |
1140 UMA_HISTOGRAM_COUNTS_10000("Histogram.SecondUpload.RangesSaved." + suffix, | |
1141 number_of_vectors_saved_); | |
1142 UMA_HISTOGRAM_COUNTS("Histogram.SecondUpload.RangesElementsSaved" + suffix, | |
1143 static_cast<int>(saved_ranges_size_)); | |
1144 number_of_histograms_ = 0; | |
1145 number_of_vectors_saved_ = 0; | |
1146 saved_ranges_size_ = 0; | |
1147 return; | |
1148 } | |
1149 UMA_HISTOGRAM_COUNTS_10000("Histogram.RestOfUploads.Count." + suffix, | |
1150 number_of_histograms_); | |
1151 UMA_HISTOGRAM_COUNTS_10000("Histogram.RestOfUploads.RangesSaved." + suffix, | |
1152 number_of_vectors_saved_); | |
1153 UMA_HISTOGRAM_COUNTS("Histogram.RestOfUploads.RangesElementsSaved." + suffix, | |
1154 static_cast<int>(saved_ranges_size_)); | |
1155 } | |
1156 | |
1157 // static | |
1063 void StatisticsRecorder::WriteHTMLGraph(const std::string& query, | 1158 void StatisticsRecorder::WriteHTMLGraph(const std::string& query, |
1064 std::string* output) { | 1159 std::string* output) { |
1065 if (!IsActive()) | 1160 if (!IsActive()) |
1066 return; | 1161 return; |
1067 | 1162 |
1068 Histograms snapshot; | 1163 Histograms snapshot; |
1069 GetSnapshot(query, &snapshot); | 1164 GetSnapshot(query, &snapshot); |
1070 for (Histograms::iterator it = snapshot.begin(); | 1165 for (Histograms::iterator it = snapshot.begin(); |
1071 it != snapshot.end(); | 1166 it != snapshot.end(); |
1072 ++it) { | 1167 ++it) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1133 if (!histograms_) | 1228 if (!histograms_) |
1134 return; | 1229 return; |
1135 for (HistogramMap::iterator it = histograms_->begin(); | 1230 for (HistogramMap::iterator it = histograms_->begin(); |
1136 histograms_->end() != it; | 1231 histograms_->end() != it; |
1137 ++it) { | 1232 ++it) { |
1138 if (it->first.find(query) != std::string::npos) | 1233 if (it->first.find(query) != std::string::npos) |
1139 snapshot->push_back(it->second); | 1234 snapshot->push_back(it->second); |
1140 } | 1235 } |
1141 } | 1236 } |
1142 | 1237 |
1238 CachedRanges::CachedRanges(size_t bucket_count, int initial_value) | |
1239 : ranges_(bucket_count, initial_value), | |
1240 range_checksum_(0) { | |
1241 } | |
1242 | |
1243 CachedRanges::~CachedRanges() { | |
1244 } | |
1245 | |
1246 void CachedRanges::SetBucketRange(size_t i, Histogram::Sample value) { | |
1247 DCHECK_LT(i, ranges_.size()); | |
1248 DCHECK_GE(value, 0); | |
1249 ranges_[i] = value; | |
1250 } | |
1251 | |
1252 bool CachedRanges::Equals(CachedRanges* other) const { | |
1253 if (range_checksum_ != other->range_checksum_) | |
1254 return false; | |
1255 if (ranges_.size() != other->ranges_.size()) | |
1256 return false; | |
1257 for (size_t index = 0; index < ranges_.size(); ++index) { | |
1258 if (ranges_[index] != other->ranges_[index]) | |
1259 return false; | |
1260 } | |
1261 return true; | |
1262 } | |
1263 | |
1143 // static | 1264 // static |
1144 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; | 1265 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; |
1145 // static | 1266 // static |
1267 StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL; | |
1268 // static | |
1146 base::Lock* StatisticsRecorder::lock_ = NULL; | 1269 base::Lock* StatisticsRecorder::lock_ = NULL; |
1147 // static | 1270 // static |
1148 bool StatisticsRecorder::dump_on_exit_ = false; | 1271 bool StatisticsRecorder::dump_on_exit_ = false; |
1149 | |
1150 } // namespace base | 1272 } // namespace base |
OLD | NEW |