Chromium Code Reviews| 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 |