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 |