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 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 } | 376 } |
377 } | 377 } |
378 return static_cast<Inconsistencies>(inconsistencies); | 378 return static_cast<Inconsistencies>(inconsistencies); |
379 } | 379 } |
380 | 380 |
381 Histogram::ClassType Histogram::histogram_type() const { | 381 Histogram::ClassType Histogram::histogram_type() const { |
382 return HISTOGRAM; | 382 return HISTOGRAM; |
383 } | 383 } |
384 | 384 |
385 Histogram::Sample Histogram::ranges(size_t i) const { | 385 Histogram::Sample Histogram::ranges(size_t i) const { |
386 return bucket_ranges_->range(i); | 386 return cached_ranges_->ranges(i); |
387 } | 387 } |
388 | 388 |
389 size_t Histogram::bucket_count() const { | 389 size_t Histogram::bucket_count() const { |
390 return bucket_count_; | 390 return bucket_count_; |
391 } | 391 } |
392 | 392 |
393 // Do a safe atomic snapshot of sample data. | 393 // Do a safe atomic snapshot of sample data. |
394 // This implementation assumes we are on a safe single thread. | 394 // This implementation assumes we are on a safe single thread. |
395 void Histogram::SnapshotSample(SampleSet* sample) const { | 395 void Histogram::SnapshotSample(SampleSet* sample) const { |
396 // Note locking not done in this version!!! | 396 // Note locking not done in this version!!! |
(...skipping 19 matching lines...) Expand all Loading... |
416 return CalculateRangeChecksum() == range_checksum_; | 416 return CalculateRangeChecksum() == range_checksum_; |
417 } | 417 } |
418 | 418 |
419 Histogram::Histogram(const std::string& name, Sample minimum, | 419 Histogram::Histogram(const std::string& name, Sample minimum, |
420 Sample maximum, size_t bucket_count) | 420 Sample maximum, size_t bucket_count) |
421 : HistogramBase(name), | 421 : HistogramBase(name), |
422 declared_min_(minimum), | 422 declared_min_(minimum), |
423 declared_max_(maximum), | 423 declared_max_(maximum), |
424 bucket_count_(bucket_count), | 424 bucket_count_(bucket_count), |
425 flags_(kNoFlags), | 425 flags_(kNoFlags), |
426 bucket_ranges_(new BucketRanges(bucket_count + 1)), | 426 cached_ranges_(new CachedRanges(bucket_count + 1, 0)), |
427 range_checksum_(0), | 427 range_checksum_(0), |
428 sample_() { | 428 sample_() { |
429 Initialize(); | 429 Initialize(); |
430 } | 430 } |
431 | 431 |
432 Histogram::Histogram(const std::string& name, TimeDelta minimum, | 432 Histogram::Histogram(const std::string& name, TimeDelta minimum, |
433 TimeDelta maximum, size_t bucket_count) | 433 TimeDelta maximum, size_t bucket_count) |
434 : HistogramBase(name), | 434 : HistogramBase(name), |
435 declared_min_(static_cast<int> (minimum.InMilliseconds())), | 435 declared_min_(static_cast<int> (minimum.InMilliseconds())), |
436 declared_max_(static_cast<int> (maximum.InMilliseconds())), | 436 declared_max_(static_cast<int> (maximum.InMilliseconds())), |
437 bucket_count_(bucket_count), | 437 bucket_count_(bucket_count), |
438 flags_(kNoFlags), | 438 flags_(kNoFlags), |
439 bucket_ranges_(new BucketRanges(bucket_count + 1)), | 439 cached_ranges_(new CachedRanges(bucket_count + 1, 0)), |
440 range_checksum_(0), | 440 range_checksum_(0), |
441 sample_() { | 441 sample_() { |
442 Initialize(); | 442 Initialize(); |
443 } | 443 } |
444 | 444 |
445 Histogram::~Histogram() { | 445 Histogram::~Histogram() { |
446 if (StatisticsRecorder::dump_on_exit()) { | 446 if (StatisticsRecorder::dump_on_exit()) { |
447 std::string output; | 447 std::string output; |
448 WriteAsciiImpl(true, "\n", &output); | 448 WriteAsciiImpl(true, "\n", &output); |
449 DLOG(INFO) << output; | 449 DLOG(INFO) << output; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
550 | 550 |
551 // Update histogram data with new sample. | 551 // Update histogram data with new sample. |
552 void Histogram::Accumulate(Sample value, Count count, size_t index) { | 552 void Histogram::Accumulate(Sample value, Count count, size_t index) { |
553 // Note locking not done in this version!!! | 553 // Note locking not done in this version!!! |
554 sample_.Accumulate(value, count, index); | 554 sample_.Accumulate(value, count, index); |
555 } | 555 } |
556 | 556 |
557 void Histogram::SetBucketRange(size_t i, Sample value) { | 557 void Histogram::SetBucketRange(size_t i, Sample value) { |
558 DCHECK_GT(bucket_count_, i); | 558 DCHECK_GT(bucket_count_, i); |
559 DCHECK_GE(value, 0); | 559 DCHECK_GE(value, 0); |
560 bucket_ranges_->set_range(i, value); | 560 cached_ranges_->SetBucketRange(i, value); |
561 } | 561 } |
562 | 562 |
563 bool Histogram::ValidateBucketRanges() const { | 563 bool Histogram::ValidateBucketRanges() const { |
564 // Standard assertions that all bucket ranges should satisfy. | 564 // Standard assertions that all bucket ranges should satisfy. |
565 DCHECK_EQ(bucket_count_ + 1, bucket_ranges_->size()); | 565 DCHECK_EQ(bucket_count_ + 1, cached_ranges_->size()); |
566 DCHECK_EQ(0, ranges(0)); | 566 DCHECK_EQ(0, ranges(0)); |
567 DCHECK_EQ(declared_min(), ranges(1)); | 567 DCHECK_EQ(declared_min(), ranges(1)); |
568 DCHECK_EQ(declared_max(), ranges(bucket_count_ - 1)); | 568 DCHECK_EQ(declared_max(), ranges(bucket_count_ - 1)); |
569 DCHECK_EQ(kSampleType_MAX, ranges(bucket_count_)); | 569 DCHECK_EQ(kSampleType_MAX, ranges(bucket_count_)); |
570 return true; | 570 return true; |
571 } | 571 } |
572 | 572 |
573 uint32 Histogram::CalculateRangeChecksum() const { | 573 uint32 Histogram::CalculateRangeChecksum() const { |
574 DCHECK_EQ(bucket_ranges_->size(), bucket_count() + 1); | 574 DCHECK_EQ(cached_ranges_->size(), bucket_count() + 1); |
575 // Seed checksum. | 575 // Seed checksum. |
576 uint32 checksum = static_cast<uint32>(bucket_ranges_->size()); | 576 uint32 checksum = static_cast<uint32>(cached_ranges_->size()); |
577 for (size_t index = 0; index < bucket_count(); ++index) | 577 for (size_t index = 0; index < bucket_count(); ++index) |
578 checksum = Crc32(checksum, ranges(index)); | 578 checksum = Crc32(checksum, ranges(index)); |
579 return checksum; | 579 return checksum; |
580 } | 580 } |
581 | 581 |
582 void Histogram::Initialize() { | 582 void Histogram::Initialize() { |
583 sample_.Resize(*this); | 583 sample_.Resize(*this); |
584 if (declared_min_ < 1) | 584 if (declared_min_ < 1) |
585 declared_min_ = 1; | 585 declared_min_ = 1; |
586 if (declared_max_ > kSampleType_MAX - 1) | 586 if (declared_max_ > kSampleType_MAX - 1) |
587 declared_max_ = kSampleType_MAX - 1; | 587 declared_max_ = kSampleType_MAX - 1; |
588 DCHECK_LE(declared_min_, declared_max_); | 588 DCHECK_LE(declared_min_, declared_max_); |
589 DCHECK_GT(bucket_count_, 1u); | 589 DCHECK_GT(bucket_count_, 1u); |
590 CHECK_LT(bucket_count_, kBucketCount_MAX); | 590 CHECK_LT(bucket_count_, kBucketCount_MAX); |
591 size_t maximal_bucket_count = declared_max_ - declared_min_ + 2; | 591 size_t maximal_bucket_count = declared_max_ - declared_min_ + 2; |
592 DCHECK_LE(bucket_count_, maximal_bucket_count); | 592 DCHECK_LE(bucket_count_, maximal_bucket_count); |
593 DCHECK_EQ(0, ranges(0)); | 593 DCHECK_EQ(0, ranges(0)); |
594 bucket_ranges_->set_range(bucket_count_, kSampleType_MAX); | 594 cached_ranges_->SetBucketRange(bucket_count_, kSampleType_MAX); |
595 } | 595 } |
596 | 596 |
597 // We generate the CRC-32 using the low order bits to select whether to XOR in | 597 // We generate the CRC-32 using the low order bits to select whether to XOR in |
598 // the reversed polynomial 0xedb88320L. This is nice and simple, and allows us | 598 // the reversed polynomial 0xedb88320L. This is nice and simple, and allows us |
599 // to keep the quotient in a uint32. Since we're not concerned about the nature | 599 // to keep the quotient in a uint32. Since we're not concerned about the nature |
600 // of corruptions (i.e., we don't care about bit sequencing, since we are | 600 // of corruptions (i.e., we don't care about bit sequencing, since we are |
601 // handling memory changes, which are more grotesque) so we don't bother to | 601 // handling memory changes, which are more grotesque) so we don't bother to |
602 // get the CRC correct for big-endian vs little-ending calculations. All we | 602 // get the CRC correct for big-endian vs little-ending calculations. All we |
603 // need is a nice hash, that tends to depend on all the bits of the sample, with | 603 // need is a nice hash, that tends to depend on all the bits of the sample, with |
604 // very little chance of changes in one place impacting changes in another | 604 // very little chance of changes in one place impacting changes in another |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
993 | 993 |
994 CustomHistogram::CustomHistogram(const std::string& name, | 994 CustomHistogram::CustomHistogram(const std::string& name, |
995 const std::vector<Sample>& custom_ranges) | 995 const std::vector<Sample>& custom_ranges) |
996 : Histogram(name, custom_ranges[1], custom_ranges.back(), | 996 : Histogram(name, custom_ranges[1], custom_ranges.back(), |
997 custom_ranges.size()) { | 997 custom_ranges.size()) { |
998 DCHECK_GT(custom_ranges.size(), 1u); | 998 DCHECK_GT(custom_ranges.size(), 1u); |
999 DCHECK_EQ(custom_ranges[0], 0); | 999 DCHECK_EQ(custom_ranges[0], 0); |
1000 } | 1000 } |
1001 | 1001 |
1002 bool CustomHistogram::SerializeRanges(Pickle* pickle) const { | 1002 bool CustomHistogram::SerializeRanges(Pickle* pickle) const { |
1003 for (size_t i = 0; i < bucket_ranges()->size(); ++i) { | 1003 for (size_t i = 0; i < cached_ranges()->size(); ++i) { |
1004 if (!pickle->WriteInt(bucket_ranges()->range(i))) | 1004 if (!pickle->WriteInt(cached_ranges()->ranges(i))) |
1005 return false; | 1005 return false; |
1006 } | 1006 } |
1007 return true; | 1007 return true; |
1008 } | 1008 } |
1009 | 1009 |
1010 // static | 1010 // static |
1011 bool CustomHistogram::DeserializeRanges( | 1011 bool CustomHistogram::DeserializeRanges( |
1012 PickleIterator* iter, std::vector<Histogram::Sample>* ranges) { | 1012 PickleIterator* iter, std::vector<Histogram::Sample>* ranges) { |
1013 for (size_t i = 0; i < ranges->size(); ++i) { | 1013 for (size_t i = 0; i < ranges->size(); ++i) { |
1014 if (!iter->ReadInt(&(*ranges)[i])) | 1014 if (!iter->ReadInt(&(*ranges)[i])) |
1015 return false; | 1015 return false; |
1016 } | 1016 } |
1017 return true; | 1017 return true; |
1018 } | 1018 } |
1019 | 1019 |
1020 void CustomHistogram::InitializedCustomBucketRange( | 1020 void CustomHistogram::InitializedCustomBucketRange( |
1021 const std::vector<Sample>& custom_ranges) { | 1021 const std::vector<Sample>& custom_ranges) { |
1022 DCHECK_GT(custom_ranges.size(), 1u); | 1022 DCHECK_GT(custom_ranges.size(), 1u); |
1023 DCHECK_EQ(custom_ranges[0], 0); | 1023 DCHECK_EQ(custom_ranges[0], 0); |
1024 DCHECK_LE(custom_ranges.size(), bucket_count()); | 1024 DCHECK_LE(custom_ranges.size(), bucket_count()); |
1025 for (size_t index = 0; index < custom_ranges.size(); ++index) | 1025 for (size_t index = 0; index < custom_ranges.size(); ++index) |
1026 SetBucketRange(index, custom_ranges[index]); | 1026 SetBucketRange(index, custom_ranges[index]); |
1027 ResetRangeChecksum(); | 1027 ResetRangeChecksum(); |
1028 } | 1028 } |
1029 | 1029 |
1030 double CustomHistogram::GetBucketSize(Count current, size_t i) const { | 1030 double CustomHistogram::GetBucketSize(Count current, size_t i) const { |
1031 return 1; | 1031 return 1; |
1032 } | 1032 } |
1033 | 1033 |
| 1034 CachedRanges::CachedRanges(size_t bucket_count, int initial_value) |
| 1035 : ranges_(bucket_count, initial_value), |
| 1036 range_checksum_(0) { |
| 1037 } |
| 1038 |
| 1039 CachedRanges::~CachedRanges() { |
| 1040 } |
| 1041 |
| 1042 void CachedRanges::SetBucketRange(size_t i, Histogram::Sample value) { |
| 1043 DCHECK_LT(i, ranges_.size()); |
| 1044 DCHECK_GE(value, 0); |
| 1045 ranges_[i] = value; |
| 1046 } |
| 1047 |
| 1048 bool CachedRanges::Equals(CachedRanges* other) const { |
| 1049 if (range_checksum_ != other->range_checksum_) |
| 1050 return false; |
| 1051 if (ranges_.size() != other->ranges_.size()) |
| 1052 return false; |
| 1053 for (size_t index = 0; index < ranges_.size(); ++index) { |
| 1054 if (ranges_[index] != other->ranges_[index]) |
| 1055 return false; |
| 1056 } |
| 1057 return true; |
| 1058 } |
| 1059 |
1034 } // namespace base | 1060 } // namespace base |
OLD | NEW |