Chromium Code Reviews| 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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 count += i; | 126 count += i; |
| 127 } | 127 } |
| 128 DCHECK_EQ(count, redundant_count_); | 128 DCHECK_EQ(count, redundant_count_); |
| 129 return count == redundant_count_; | 129 return count == redundant_count_; |
| 130 } | 130 } |
| 131 | 131 |
| 132 Histogram* Histogram::FactoryGet(const string& name, | 132 Histogram* Histogram::FactoryGet(const string& name, |
| 133 Sample minimum, | 133 Sample minimum, |
| 134 Sample maximum, | 134 Sample maximum, |
| 135 size_t bucket_count, | 135 size_t bucket_count, |
| 136 Flags flags) { | 136 int32 flags) { |
| 137 CHECK(InspectConstructionArguments(name, &minimum, &maximum, &bucket_count)); | 137 CHECK(InspectConstructionArguments(name, &minimum, &maximum, &bucket_count)); |
| 138 | 138 |
| 139 Histogram* histogram = StatisticsRecorder::FindHistogram(name); | 139 Histogram* histogram = StatisticsRecorder::FindHistogram(name); |
| 140 if (!histogram) { | 140 if (!histogram) { |
| 141 // To avoid racy destruction at shutdown, the following will be leaked. | 141 // To avoid racy destruction at shutdown, the following will be leaked. |
| 142 BucketRanges* ranges = new BucketRanges(bucket_count + 1); | 142 BucketRanges* ranges = new BucketRanges(bucket_count + 1); |
| 143 InitializeBucketRanges(minimum, maximum, bucket_count, ranges); | 143 InitializeBucketRanges(minimum, maximum, bucket_count, ranges); |
| 144 const BucketRanges* registered_ranges = | 144 const BucketRanges* registered_ranges = |
| 145 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); | 145 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); |
| 146 | 146 |
| 147 Histogram* tentative_histogram = | 147 Histogram* tentative_histogram = |
| 148 new Histogram(name, minimum, maximum, bucket_count, registered_ranges); | 148 new Histogram(name, minimum, maximum, bucket_count, registered_ranges); |
| 149 tentative_histogram->SetFlags(flags); | 149 tentative_histogram->SetFlags(flags); |
| 150 histogram = | 150 histogram = |
| 151 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); | 151 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
| 152 } | 152 } |
| 153 | 153 |
| 154 CHECK_EQ(HISTOGRAM, histogram->histogram_type()); | 154 CHECK_EQ(HISTOGRAM, histogram->histogram_type()); |
| 155 CHECK(histogram->HasConstructionArguments(minimum, maximum, bucket_count)); | 155 CHECK(histogram->HasConstructionArguments(minimum, maximum, bucket_count)); |
| 156 return histogram; | 156 return histogram; |
| 157 } | 157 } |
| 158 | 158 |
| 159 Histogram* Histogram::FactoryTimeGet(const string& name, | 159 Histogram* Histogram::FactoryTimeGet(const string& name, |
| 160 TimeDelta minimum, | 160 TimeDelta minimum, |
| 161 TimeDelta maximum, | 161 TimeDelta maximum, |
| 162 size_t bucket_count, | 162 size_t bucket_count, |
| 163 Flags flags) { | 163 int32 flags) { |
| 164 return FactoryGet(name, minimum.InMilliseconds(), maximum.InMilliseconds(), | 164 return FactoryGet(name, minimum.InMilliseconds(), maximum.InMilliseconds(), |
| 165 bucket_count, flags); | 165 bucket_count, flags); |
| 166 } | 166 } |
| 167 | 167 |
| 168 TimeTicks Histogram::DebugNow() { | 168 TimeTicks Histogram::DebugNow() { |
| 169 #ifndef NDEBUG | 169 #ifndef NDEBUG |
| 170 return TimeTicks::Now(); | 170 return TimeTicks::Now(); |
| 171 #else | 171 #else |
| 172 return TimeTicks(); | 172 return TimeTicks(); |
| 173 #endif | 173 #endif |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 433 Histogram::Histogram(const string& name, | 433 Histogram::Histogram(const string& name, |
| 434 Sample minimum, | 434 Sample minimum, |
| 435 Sample maximum, | 435 Sample maximum, |
| 436 size_t bucket_count, | 436 size_t bucket_count, |
| 437 const BucketRanges* ranges) | 437 const BucketRanges* ranges) |
| 438 : HistogramBase(name), | 438 : HistogramBase(name), |
| 439 bucket_ranges_(ranges), | 439 bucket_ranges_(ranges), |
| 440 declared_min_(minimum), | 440 declared_min_(minimum), |
| 441 declared_max_(maximum), | 441 declared_max_(maximum), |
| 442 bucket_count_(bucket_count), | 442 bucket_count_(bucket_count), |
| 443 flags_(kNoFlags), | |
| 444 sample_(bucket_count) {} | 443 sample_(bucket_count) {} |
| 445 | 444 |
| 446 Histogram::~Histogram() { | 445 Histogram::~Histogram() { |
| 447 if (StatisticsRecorder::dump_on_exit()) { | 446 if (StatisticsRecorder::dump_on_exit()) { |
| 448 string output; | 447 string output; |
| 449 WriteAsciiImpl(true, "\n", &output); | 448 WriteAsciiImpl(true, "\n", &output); |
| 450 DLOG(INFO) << output; | 449 DLOG(INFO) << output; |
| 451 } | 450 } |
| 452 } | 451 } |
| 453 | 452 |
| 454 // static | 453 // static |
| 455 bool Histogram::InspectConstructionArguments(const string& name, | 454 bool Histogram::InspectConstructionArguments(const string& name, |
| 456 Sample* minimum, | 455 Sample* minimum, |
| 457 Sample* maximum, | 456 Sample* maximum, |
| 458 size_t* bucket_count) { | 457 size_t* bucket_count) { |
| 459 // Defensive code for backward compatibility. | 458 // Defensive code for backward compatibility. |
| 460 if (*minimum < 1) { | 459 if (*minimum < 1) { |
| 461 DVLOG(1) << "Histogram: " << name << " has bad minimum: " << *minimum; | 460 DVLOG(1) << "Histogram: " << name << " has bad minimum: " << *minimum; |
| 462 *minimum = 1; | 461 *minimum = 1; |
| 463 } | 462 } |
| 464 if (*maximum >= kSampleType_MAX) { | 463 if (*maximum >= kSampleType_MAX) { |
| 465 DVLOG(1) << "Histogram: " << name << " has bad maximum: " << *maximum; | 464 DVLOG(1) << "Histogram: " << name << " has bad maximum: " << *maximum; |
| 466 *maximum = kSampleType_MAX - 1; | 465 *maximum = kSampleType_MAX; |
|
Ilya Sherman
2012/08/04 01:18:35
This doesn't seem right -- kSampleType_MAX fails t
kaiwang
2012/08/08 03:59:33
Good catch! It's fixed in another CL
Ilya Sherman
2012/08/08 05:00:29
Ok. In that case, can you move this change into t
kaiwang
2012/08/08 22:17:08
That's already submitted
Ilya Sherman
2012/08/08 22:49:40
Could you rebase this CL, then? It's still showin
kaiwang
2012/08/08 23:03:37
See patch set 4
| |
| 467 } | 466 } |
| 468 | 467 |
| 469 if (*bucket_count < 3 || *bucket_count >= kBucketCount_MAX) | 468 if (*bucket_count < 3 || *bucket_count >= kBucketCount_MAX) |
| 470 return false; | 469 return false; |
| 471 if (*bucket_count > static_cast<size_t>(*maximum - *minimum + 2)) | 470 if (*bucket_count > static_cast<size_t>(*maximum - *minimum + 2)) |
| 472 return false; | 471 return false; |
| 473 return true; | 472 return true; |
| 474 } | 473 } |
| 475 | 474 |
| 476 bool Histogram::SerializeRanges(Pickle* pickle) const { | 475 bool Histogram::SerializeRanges(Pickle* pickle) const { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 515 DCHECK_GT(ranges(i + 1), ranges(i)); | 514 DCHECK_GT(ranges(i + 1), ranges(i)); |
| 516 static const double kTransitionWidth = 5; | 515 static const double kTransitionWidth = 5; |
| 517 double denominator = ranges(i + 1) - ranges(i); | 516 double denominator = ranges(i + 1) - ranges(i); |
| 518 if (denominator > kTransitionWidth) | 517 if (denominator > kTransitionWidth) |
| 519 denominator = kTransitionWidth; // Stop trying to normalize. | 518 denominator = kTransitionWidth; // Stop trying to normalize. |
| 520 return current/denominator; | 519 return current/denominator; |
| 521 } | 520 } |
| 522 | 521 |
| 523 const string Histogram::GetAsciiBucketRange(size_t i) const { | 522 const string Histogram::GetAsciiBucketRange(size_t i) const { |
| 524 string result; | 523 string result; |
| 525 if (kHexRangePrintingFlag & flags_) | 524 if (kHexRangePrintingFlag & flags()) |
| 526 StringAppendF(&result, "%#x", ranges(i)); | 525 StringAppendF(&result, "%#x", ranges(i)); |
| 527 else | 526 else |
| 528 StringAppendF(&result, "%d", ranges(i)); | 527 StringAppendF(&result, "%d", ranges(i)); |
| 529 return result; | 528 return result; |
| 530 } | 529 } |
| 531 | 530 |
| 532 // Update histogram data with new sample. | 531 // Update histogram data with new sample. |
| 533 void Histogram::Accumulate(Sample value, Count count, size_t index) { | 532 void Histogram::Accumulate(Sample value, Count count, size_t index) { |
| 534 // Note locking not done in this version!!! | 533 // Note locking not done in this version!!! |
| 535 sample_.Accumulate(value, count, index); | 534 sample_.Accumulate(value, count, index); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 620 "Histogram: %s recorded %d samples", | 619 "Histogram: %s recorded %d samples", |
| 621 histogram_name().c_str(), | 620 histogram_name().c_str(), |
| 622 sample_count); | 621 sample_count); |
| 623 if (0 == sample_count) { | 622 if (0 == sample_count) { |
| 624 DCHECK_EQ(snapshot.sum(), 0); | 623 DCHECK_EQ(snapshot.sum(), 0); |
| 625 } else { | 624 } else { |
| 626 double average = static_cast<float>(snapshot.sum()) / sample_count; | 625 double average = static_cast<float>(snapshot.sum()) / sample_count; |
| 627 | 626 |
| 628 StringAppendF(output, ", average = %.1f", average); | 627 StringAppendF(output, ", average = %.1f", average); |
| 629 } | 628 } |
| 630 if (flags_ & ~kHexRangePrintingFlag) | 629 if (flags() & ~kHexRangePrintingFlag) |
| 631 StringAppendF(output, " (flags = 0x%x)", flags_ & ~kHexRangePrintingFlag); | 630 StringAppendF(output, " (flags = 0x%x)", flags() & ~kHexRangePrintingFlag); |
| 632 } | 631 } |
| 633 | 632 |
| 634 void Histogram::WriteAsciiBucketContext(const int64 past, | 633 void Histogram::WriteAsciiBucketContext(const int64 past, |
| 635 const Count current, | 634 const Count current, |
| 636 const int64 remaining, | 635 const int64 remaining, |
| 637 const size_t i, | 636 const size_t i, |
| 638 string* output) const { | 637 string* output) const { |
| 639 double scaled_sum = (past + current + remaining) / 100.0; | 638 double scaled_sum = (past + current + remaining) / 100.0; |
| 640 WriteAsciiBucketValue(current, scaled_sum, output); | 639 WriteAsciiBucketValue(current, scaled_sum, output); |
| 641 if (0 < i) { | 640 if (0 < i) { |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 669 // LinearHistogram: This histogram uses a traditional set of evenly spaced | 668 // LinearHistogram: This histogram uses a traditional set of evenly spaced |
| 670 // buckets. | 669 // buckets. |
| 671 //------------------------------------------------------------------------------ | 670 //------------------------------------------------------------------------------ |
| 672 | 671 |
| 673 LinearHistogram::~LinearHistogram() {} | 672 LinearHistogram::~LinearHistogram() {} |
| 674 | 673 |
| 675 Histogram* LinearHistogram::FactoryGet(const string& name, | 674 Histogram* LinearHistogram::FactoryGet(const string& name, |
| 676 Sample minimum, | 675 Sample minimum, |
| 677 Sample maximum, | 676 Sample maximum, |
| 678 size_t bucket_count, | 677 size_t bucket_count, |
| 679 Flags flags) { | 678 int32 flags) { |
| 680 CHECK(Histogram::InspectConstructionArguments(name, &minimum, &maximum, | 679 CHECK(Histogram::InspectConstructionArguments(name, &minimum, &maximum, |
| 681 &bucket_count)); | 680 &bucket_count)); |
| 682 | 681 |
| 683 Histogram* histogram = StatisticsRecorder::FindHistogram(name); | 682 Histogram* histogram = StatisticsRecorder::FindHistogram(name); |
| 684 if (!histogram) { | 683 if (!histogram) { |
| 685 // To avoid racy destruction at shutdown, the following will be leaked. | 684 // To avoid racy destruction at shutdown, the following will be leaked. |
| 686 BucketRanges* ranges = new BucketRanges(bucket_count + 1); | 685 BucketRanges* ranges = new BucketRanges(bucket_count + 1); |
| 687 InitializeBucketRanges(minimum, maximum, bucket_count, ranges); | 686 InitializeBucketRanges(minimum, maximum, bucket_count, ranges); |
| 688 const BucketRanges* registered_ranges = | 687 const BucketRanges* registered_ranges = |
| 689 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); | 688 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); |
| 690 | 689 |
| 691 LinearHistogram* tentative_histogram = | 690 LinearHistogram* tentative_histogram = |
| 692 new LinearHistogram(name, minimum, maximum, bucket_count, | 691 new LinearHistogram(name, minimum, maximum, bucket_count, |
| 693 registered_ranges); | 692 registered_ranges); |
| 694 tentative_histogram->SetFlags(flags); | 693 tentative_histogram->SetFlags(flags); |
| 695 histogram = | 694 histogram = |
| 696 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); | 695 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
| 697 } | 696 } |
| 698 | 697 |
| 699 CHECK_EQ(LINEAR_HISTOGRAM, histogram->histogram_type()); | 698 CHECK_EQ(LINEAR_HISTOGRAM, histogram->histogram_type()); |
| 700 CHECK(histogram->HasConstructionArguments(minimum, maximum, bucket_count)); | 699 CHECK(histogram->HasConstructionArguments(minimum, maximum, bucket_count)); |
| 701 return histogram; | 700 return histogram; |
| 702 } | 701 } |
| 703 | 702 |
| 704 Histogram* LinearHistogram::FactoryTimeGet(const string& name, | 703 Histogram* LinearHistogram::FactoryTimeGet(const string& name, |
| 705 TimeDelta minimum, | 704 TimeDelta minimum, |
| 706 TimeDelta maximum, | 705 TimeDelta maximum, |
| 707 size_t bucket_count, | 706 size_t bucket_count, |
| 708 Flags flags) { | 707 int32 flags) { |
| 709 return FactoryGet(name, minimum.InMilliseconds(), maximum.InMilliseconds(), | 708 return FactoryGet(name, minimum.InMilliseconds(), maximum.InMilliseconds(), |
| 710 bucket_count, flags); | 709 bucket_count, flags); |
| 711 } | 710 } |
| 712 | 711 |
| 713 Histogram::ClassType LinearHistogram::histogram_type() const { | 712 Histogram::ClassType LinearHistogram::histogram_type() const { |
| 714 return LINEAR_HISTOGRAM; | 713 return LINEAR_HISTOGRAM; |
| 715 } | 714 } |
| 716 | 715 |
| 717 void LinearHistogram::SetRangeDescriptions( | 716 void LinearHistogram::SetRangeDescriptions( |
| 718 const DescriptionPair descriptions[]) { | 717 const DescriptionPair descriptions[]) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 764 ranges->set_range(i, static_cast<Sample>(linear_range + 0.5)); | 763 ranges->set_range(i, static_cast<Sample>(linear_range + 0.5)); |
| 765 } | 764 } |
| 766 ranges->set_range(ranges->size() - 1, HistogramBase::kSampleType_MAX); | 765 ranges->set_range(ranges->size() - 1, HistogramBase::kSampleType_MAX); |
| 767 ranges->ResetChecksum(); | 766 ranges->ResetChecksum(); |
| 768 } | 767 } |
| 769 | 768 |
| 770 //------------------------------------------------------------------------------ | 769 //------------------------------------------------------------------------------ |
| 771 // This section provides implementation for BooleanHistogram. | 770 // This section provides implementation for BooleanHistogram. |
| 772 //------------------------------------------------------------------------------ | 771 //------------------------------------------------------------------------------ |
| 773 | 772 |
| 774 Histogram* BooleanHistogram::FactoryGet(const string& name, Flags flags) { | 773 Histogram* BooleanHistogram::FactoryGet(const string& name, int32 flags) { |
| 775 Histogram* histogram = StatisticsRecorder::FindHistogram(name); | 774 Histogram* histogram = StatisticsRecorder::FindHistogram(name); |
| 776 if (!histogram) { | 775 if (!histogram) { |
| 777 // To avoid racy destruction at shutdown, the following will be leaked. | 776 // To avoid racy destruction at shutdown, the following will be leaked. |
| 778 BucketRanges* ranges = new BucketRanges(4); | 777 BucketRanges* ranges = new BucketRanges(4); |
| 779 LinearHistogram::InitializeBucketRanges(1, 2, 3, ranges); | 778 LinearHistogram::InitializeBucketRanges(1, 2, 3, ranges); |
| 780 const BucketRanges* registered_ranges = | 779 const BucketRanges* registered_ranges = |
| 781 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); | 780 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); |
| 782 | 781 |
| 783 BooleanHistogram* tentative_histogram = | 782 BooleanHistogram* tentative_histogram = |
| 784 new BooleanHistogram(name, registered_ranges); | 783 new BooleanHistogram(name, registered_ranges); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 802 BooleanHistogram::BooleanHistogram(const string& name, | 801 BooleanHistogram::BooleanHistogram(const string& name, |
| 803 const BucketRanges* ranges) | 802 const BucketRanges* ranges) |
| 804 : LinearHistogram(name, 1, 2, 3, ranges) {} | 803 : LinearHistogram(name, 1, 2, 3, ranges) {} |
| 805 | 804 |
| 806 //------------------------------------------------------------------------------ | 805 //------------------------------------------------------------------------------ |
| 807 // CustomHistogram: | 806 // CustomHistogram: |
| 808 //------------------------------------------------------------------------------ | 807 //------------------------------------------------------------------------------ |
| 809 | 808 |
| 810 Histogram* CustomHistogram::FactoryGet(const string& name, | 809 Histogram* CustomHistogram::FactoryGet(const string& name, |
| 811 const vector<Sample>& custom_ranges, | 810 const vector<Sample>& custom_ranges, |
| 812 Flags flags) { | 811 int32 flags) { |
| 813 CHECK(ValidateCustomRanges(custom_ranges)); | 812 CHECK(ValidateCustomRanges(custom_ranges)); |
| 814 | 813 |
| 815 Histogram* histogram = StatisticsRecorder::FindHistogram(name); | 814 Histogram* histogram = StatisticsRecorder::FindHistogram(name); |
| 816 if (!histogram) { | 815 if (!histogram) { |
| 817 BucketRanges* ranges = CreateBucketRangesFromCustomRanges(custom_ranges); | 816 BucketRanges* ranges = CreateBucketRangesFromCustomRanges(custom_ranges); |
| 818 const BucketRanges* registered_ranges = | 817 const BucketRanges* registered_ranges = |
| 819 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); | 818 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); |
| 820 | 819 |
| 821 // To avoid racy destruction at shutdown, the following will be leaked. | 820 // To avoid racy destruction at shutdown, the following will be leaked. |
| 822 CustomHistogram* tentative_histogram = | 821 CustomHistogram* tentative_histogram = |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 905 | 904 |
| 906 BucketRanges* bucket_ranges = new BucketRanges(ranges.size()); | 905 BucketRanges* bucket_ranges = new BucketRanges(ranges.size()); |
| 907 for (size_t i = 0; i < ranges.size(); i++) { | 906 for (size_t i = 0; i < ranges.size(); i++) { |
| 908 bucket_ranges->set_range(i, ranges[i]); | 907 bucket_ranges->set_range(i, ranges[i]); |
| 909 } | 908 } |
| 910 bucket_ranges->ResetChecksum(); | 909 bucket_ranges->ResetChecksum(); |
| 911 return bucket_ranges; | 910 return bucket_ranges; |
| 912 } | 911 } |
| 913 | 912 |
| 914 } // namespace base | 913 } // namespace base |
| OLD | NEW |