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" |
11 | 11 |
12 #include <math.h> | 12 #include <math.h> |
13 | 13 |
14 #include <algorithm> | 14 #include <algorithm> |
15 #include <string> | 15 #include <string> |
16 | 16 |
17 #include "base/compiler_specific.h" | 17 #include "base/compiler_specific.h" |
18 #include "base/debug/alias.h" | 18 #include "base/debug/alias.h" |
19 #include "base/logging.h" | 19 #include "base/logging.h" |
| 20 #include "base/memory/persistent_memory_allocator.h" |
20 #include "base/metrics/histogram_macros.h" | 21 #include "base/metrics/histogram_macros.h" |
| 22 #include "base/metrics/histogram_persistence.h" |
21 #include "base/metrics/metrics_hashes.h" | 23 #include "base/metrics/metrics_hashes.h" |
22 #include "base/metrics/sample_vector.h" | 24 #include "base/metrics/sample_vector.h" |
23 #include "base/metrics/statistics_recorder.h" | 25 #include "base/metrics/statistics_recorder.h" |
24 #include "base/pickle.h" | 26 #include "base/pickle.h" |
25 #include "base/strings/string_util.h" | 27 #include "base/strings/string_util.h" |
26 #include "base/strings/stringprintf.h" | 28 #include "base/strings/stringprintf.h" |
27 #include "base/synchronization/lock.h" | 29 #include "base/synchronization/lock.h" |
28 #include "base/values.h" | 30 #include "base/values.h" |
29 | 31 |
30 namespace base { | 32 namespace base { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 } | 78 } |
77 | 79 |
78 } // namespace | 80 } // namespace |
79 | 81 |
80 typedef HistogramBase::Count Count; | 82 typedef HistogramBase::Count Count; |
81 typedef HistogramBase::Sample Sample; | 83 typedef HistogramBase::Sample Sample; |
82 | 84 |
83 // static | 85 // static |
84 const size_t Histogram::kBucketCount_MAX = 16384u; | 86 const size_t Histogram::kBucketCount_MAX = 16384u; |
85 | 87 |
86 HistogramBase* Histogram::FactoryGet(const std::string& name, | 88 // static |
87 Sample minimum, | 89 HistogramBase* Histogram::FactoryGet( |
88 Sample maximum, | 90 std::function<BucketRanges*()> create_ranges, |
89 size_t bucket_count, | 91 std::function<HistogramBase*(const BucketRanges*)> heap_alloc, |
90 int32 flags) { | 92 std::function<void(HistogramBase*)> fill_histogram, |
91 bool valid_arguments = | 93 HistogramType histogram_type, |
92 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count); | 94 const std::string& name, |
93 DCHECK(valid_arguments); | 95 Sample minimum, |
| 96 Sample maximum, |
| 97 size_t bucket_count, |
| 98 int32 flags) { |
| 99 ImportPersistentHistograms(); |
94 | 100 |
95 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); | 101 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); |
96 if (!histogram) { | 102 if (!histogram) { |
97 // To avoid racy destruction at shutdown, the following will be leaked. | 103 // To avoid racy destruction at shutdown, the following will be leaked. |
98 BucketRanges* ranges = new BucketRanges(bucket_count + 1); | 104 const BucketRanges* created_ranges = create_ranges(); |
99 InitializeBucketRanges(minimum, maximum, ranges); | |
100 const BucketRanges* registered_ranges = | 105 const BucketRanges* registered_ranges = |
101 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); | 106 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(created_ranges); |
102 | 107 |
103 Histogram* tentative_histogram = | 108 // Sometimes the bucket info is dynamically determined in create_ranges(). |
104 new Histogram(name, minimum, maximum, registered_ranges); | 109 if (bucket_count == 0) { |
| 110 bucket_count = registered_ranges->bucket_count(); |
| 111 minimum = registered_ranges->range(1); |
| 112 maximum = registered_ranges->range(bucket_count - 1); |
| 113 } |
| 114 |
| 115 PersistentMemoryAllocator::Reference histogram_ref = 0; |
| 116 HistogramBase* tentative_histogram = nullptr; |
| 117 if (allocator_) { |
| 118 flags |= kIsPersistent; |
| 119 tentative_histogram = AllocatePersistentHistogram( |
| 120 GetPersistentHistogramMemoryAllocator(), |
| 121 histogram_type, |
| 122 name, |
| 123 minimum, |
| 124 maximum, |
| 125 registered_ranges, |
| 126 flags, |
| 127 &histogram_ref); |
| 128 } |
| 129 if (!tentative_histogram) { |
| 130 flags &= ~kIsPersistent; |
| 131 tentative_histogram = heap_alloc(registered_ranges); |
| 132 } |
| 133 |
| 134 fill_histogram(tentative_histogram); |
105 | 135 |
106 tentative_histogram->SetFlags(flags); | 136 tentative_histogram->SetFlags(flags); |
107 histogram = | 137 histogram = |
108 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); | 138 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
| 139 |
| 140 // Persistent histograms need some follow-up processing. |
| 141 if (histogram_ref) { |
| 142 // If the created persistent histogram is canonical then it needs to be |
| 143 // marked as "iterable" in order to be found by other processes. |
| 144 if (histogram == tentative_histogram) |
| 145 GetPersistentHistogramMemoryAllocator()->MakeIterable(histogram_ref); |
| 146 // If it's not the canonical one then a race condition must have caused |
| 147 // two to be created. The allocator does not support releasing the |
| 148 // acquired memory so just change the type to be empty. |
| 149 else |
| 150 GetPersistentHistogramMemoryAllocator()->SetType(histogram_ref, 0); |
| 151 } |
109 } | 152 } |
110 | 153 |
111 DCHECK_EQ(HISTOGRAM, histogram->GetHistogramType()); | 154 DCHECK_EQ(histogram_type, histogram->GetHistogramType()); |
112 if (!histogram->HasConstructionArguments(minimum, maximum, bucket_count)) { | 155 if (bucket_count != 0 && |
| 156 !histogram->HasConstructionArguments(minimum, maximum, bucket_count)) { |
113 // The construction arguments do not match the existing histogram. This can | 157 // The construction arguments do not match the existing histogram. This can |
114 // come about if an extension updates in the middle of a chrome run and has | 158 // come about if an extension updates in the middle of a chrome run and has |
115 // changed one of them, or simply by bad code within Chrome itself. We | 159 // changed one of them, or simply by bad code within Chrome itself. We |
116 // return NULL here with the expectation that bad code in Chrome will crash | 160 // return NULL here with the expectation that bad code in Chrome will crash |
117 // on dereference, but extension/Pepper APIs will guard against NULL and not | 161 // on dereference, but extension/Pepper APIs will guard against NULL and not |
118 // crash. | 162 // crash. |
119 DLOG(ERROR) << "Histogram " << name << " has bad construction arguments"; | 163 DLOG(ERROR) << "Histogram " << name << " has bad construction arguments"; |
120 return NULL; | 164 return NULL; |
121 } | 165 } |
122 return histogram; | 166 return histogram; |
123 } | 167 } |
124 | 168 |
| 169 HistogramBase* Histogram::FactoryGet(const std::string& name, |
| 170 Sample minimum, |
| 171 Sample maximum, |
| 172 size_t bucket_count, |
| 173 int32 flags) { |
| 174 bool valid_arguments = |
| 175 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count); |
| 176 DCHECK(valid_arguments); |
| 177 |
| 178 return FactoryGet( |
| 179 [=]()->BucketRanges* { |
| 180 BucketRanges* ranges = new BucketRanges(bucket_count + 1); |
| 181 InitializeBucketRanges(minimum, maximum, ranges); |
| 182 return ranges; |
| 183 }, |
| 184 [=, &name](const BucketRanges* ranges)->HistogramBase* { |
| 185 return new Histogram(name, minimum, maximum, ranges); |
| 186 }, |
| 187 [=](HistogramBase* histogram) {}, |
| 188 HISTOGRAM, name, minimum, maximum, bucket_count, flags); |
| 189 } |
| 190 |
125 HistogramBase* Histogram::FactoryTimeGet(const std::string& name, | 191 HistogramBase* Histogram::FactoryTimeGet(const std::string& name, |
126 TimeDelta minimum, | 192 TimeDelta minimum, |
127 TimeDelta maximum, | 193 TimeDelta maximum, |
128 size_t bucket_count, | 194 size_t bucket_count, |
129 int32 flags) { | 195 int32 flags) { |
130 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()), | 196 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()), |
131 static_cast<Sample>(maximum.InMilliseconds()), bucket_count, | 197 static_cast<Sample>(maximum.InMilliseconds()), bucket_count, |
132 flags); | 198 flags); |
133 } | 199 } |
134 | 200 |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 Sample maximum, | 402 Sample maximum, |
337 const BucketRanges* ranges) | 403 const BucketRanges* ranges) |
338 : HistogramBase(name), | 404 : HistogramBase(name), |
339 bucket_ranges_(ranges), | 405 bucket_ranges_(ranges), |
340 declared_min_(minimum), | 406 declared_min_(minimum), |
341 declared_max_(maximum) { | 407 declared_max_(maximum) { |
342 if (ranges) | 408 if (ranges) |
343 samples_.reset(new SampleVector(HashMetricName(name), ranges)); | 409 samples_.reset(new SampleVector(HashMetricName(name), ranges)); |
344 } | 410 } |
345 | 411 |
| 412 Histogram::Histogram(const std::string& name, |
| 413 Sample minimum, |
| 414 Sample maximum, |
| 415 const BucketRanges* ranges, |
| 416 HistogramBase::AtomicCount* counts, |
| 417 size_t counts_size, |
| 418 HistogramSamples::Metadata* meta) |
| 419 : HistogramBase(name), |
| 420 bucket_ranges_(ranges), |
| 421 declared_min_(minimum), |
| 422 declared_max_(maximum) { |
| 423 if (ranges) |
| 424 samples_.reset(new SampleVector(HashMetricName(name), |
| 425 counts, counts_size, meta, ranges)); |
| 426 } |
| 427 |
346 Histogram::~Histogram() { | 428 Histogram::~Histogram() { |
347 } | 429 } |
348 | 430 |
349 bool Histogram::PrintEmptyBucket(size_t index) const { | 431 bool Histogram::PrintEmptyBucket(size_t index) const { |
350 return true; | 432 return true; |
351 } | 433 } |
352 | 434 |
353 // Use the actual bucket widths (like a linear histogram) until the widths get | 435 // Use the actual bucket widths (like a linear histogram) until the widths get |
354 // over some transition value, and then use that transition width. Exponentials | 436 // over some transition value, and then use that transition width. Exponentials |
355 // get so big so fast (and we don't expect to see a lot of entries in the large | 437 // get so big so fast (and we don't expect to see a lot of entries in the large |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 const std::string& name, | 668 const std::string& name, |
587 Sample minimum, | 669 Sample minimum, |
588 Sample maximum, | 670 Sample maximum, |
589 size_t bucket_count, | 671 size_t bucket_count, |
590 int32 flags, | 672 int32 flags, |
591 const DescriptionPair descriptions[]) { | 673 const DescriptionPair descriptions[]) { |
592 bool valid_arguments = Histogram::InspectConstructionArguments( | 674 bool valid_arguments = Histogram::InspectConstructionArguments( |
593 name, &minimum, &maximum, &bucket_count); | 675 name, &minimum, &maximum, &bucket_count); |
594 DCHECK(valid_arguments); | 676 DCHECK(valid_arguments); |
595 | 677 |
596 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); | 678 return Histogram::FactoryGet( |
597 if (!histogram) { | 679 [=]()->BucketRanges* { |
598 // To avoid racy destruction at shutdown, the following will be leaked. | 680 BucketRanges* ranges = new BucketRanges(bucket_count + 1); |
599 BucketRanges* ranges = new BucketRanges(bucket_count + 1); | 681 InitializeBucketRanges(minimum, maximum, ranges); |
600 InitializeBucketRanges(minimum, maximum, ranges); | 682 return ranges; |
601 const BucketRanges* registered_ranges = | 683 }, |
602 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); | 684 [=, &name](const BucketRanges* ranges)->HistogramBase* { |
603 | 685 return new LinearHistogram(name, minimum, maximum, ranges); |
604 LinearHistogram* tentative_histogram = | 686 }, |
605 new LinearHistogram(name, minimum, maximum, registered_ranges); | 687 [=](HistogramBase* base) { |
606 | 688 LinearHistogram* histogram = static_cast<LinearHistogram*>(base); |
607 // Set range descriptions. | 689 // Set range descriptions. |
608 if (descriptions) { | 690 if (descriptions) { |
609 for (int i = 0; descriptions[i].description; ++i) { | 691 for (int i = 0; descriptions[i].description; ++i) { |
610 tentative_histogram->bucket_description_[descriptions[i].sample] = | 692 histogram->bucket_description_[descriptions[i].sample] = |
611 descriptions[i].description; | 693 descriptions[i].description; |
| 694 } |
612 } | 695 } |
613 } | 696 }, |
614 | 697 LINEAR_HISTOGRAM, name, minimum, maximum, bucket_count, flags); |
615 tentative_histogram->SetFlags(flags); | |
616 histogram = | |
617 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); | |
618 } | |
619 | |
620 DCHECK_EQ(LINEAR_HISTOGRAM, histogram->GetHistogramType()); | |
621 if (!histogram->HasConstructionArguments(minimum, maximum, bucket_count)) { | |
622 // The construction arguments do not match the existing histogram. This can | |
623 // come about if an extension updates in the middle of a chrome run and has | |
624 // changed one of them, or simply by bad code within Chrome itself. We | |
625 // return NULL here with the expectation that bad code in Chrome will crash | |
626 // on dereference, but extension/Pepper APIs will guard against NULL and not | |
627 // crash. | |
628 DLOG(ERROR) << "Histogram " << name << " has bad construction arguments"; | |
629 return NULL; | |
630 } | |
631 return histogram; | |
632 } | 698 } |
633 | 699 |
634 HistogramType LinearHistogram::GetHistogramType() const { | 700 HistogramType LinearHistogram::GetHistogramType() const { |
635 return LINEAR_HISTOGRAM; | 701 return LINEAR_HISTOGRAM; |
636 } | 702 } |
637 | 703 |
638 LinearHistogram::LinearHistogram(const std::string& name, | 704 LinearHistogram::LinearHistogram(const std::string& name, |
639 Sample minimum, | 705 Sample minimum, |
640 Sample maximum, | 706 Sample maximum, |
641 const BucketRanges* ranges) | 707 const BucketRanges* ranges) |
642 : Histogram(name, minimum, maximum, ranges) { | 708 : Histogram(name, minimum, maximum, ranges) { |
643 } | 709 } |
644 | 710 |
| 711 LinearHistogram::LinearHistogram(const std::string& name, |
| 712 Sample minimum, |
| 713 Sample maximum, |
| 714 const BucketRanges* ranges, |
| 715 HistogramBase::AtomicCount* counts, |
| 716 size_t counts_size, |
| 717 HistogramSamples::Metadata* meta) |
| 718 : Histogram(name, |
| 719 minimum, |
| 720 maximum, |
| 721 ranges, |
| 722 counts, |
| 723 counts_size, |
| 724 meta) {} |
| 725 |
645 double LinearHistogram::GetBucketSize(Count current, size_t i) const { | 726 double LinearHistogram::GetBucketSize(Count current, size_t i) const { |
646 DCHECK_GT(ranges(i + 1), ranges(i)); | 727 DCHECK_GT(ranges(i + 1), ranges(i)); |
647 // Adjacent buckets with different widths would have "surprisingly" many (few) | 728 // Adjacent buckets with different widths would have "surprisingly" many (few) |
648 // samples in a histogram if we didn't normalize this way. | 729 // samples in a histogram if we didn't normalize this way. |
649 double denominator = ranges(i + 1) - ranges(i); | 730 double denominator = ranges(i + 1) - ranges(i); |
650 return current/denominator; | 731 return current/denominator; |
651 } | 732 } |
652 | 733 |
653 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const { | 734 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const { |
654 int range = ranges(i); | 735 int range = ranges(i); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 } | 781 } |
701 return histogram; | 782 return histogram; |
702 } | 783 } |
703 | 784 |
704 //------------------------------------------------------------------------------ | 785 //------------------------------------------------------------------------------ |
705 // This section provides implementation for BooleanHistogram. | 786 // This section provides implementation for BooleanHistogram. |
706 //------------------------------------------------------------------------------ | 787 //------------------------------------------------------------------------------ |
707 | 788 |
708 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name, | 789 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name, |
709 int32 flags) { | 790 int32 flags) { |
710 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); | 791 return Histogram::FactoryGet( |
711 if (!histogram) { | 792 [=]()->BucketRanges* { |
712 // To avoid racy destruction at shutdown, the following will be leaked. | 793 BucketRanges* ranges = new BucketRanges(3 + 1); |
713 BucketRanges* ranges = new BucketRanges(4); | 794 LinearHistogram::InitializeBucketRanges(1, 2, ranges); |
714 LinearHistogram::InitializeBucketRanges(1, 2, ranges); | 795 return ranges; |
715 const BucketRanges* registered_ranges = | 796 }, |
716 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); | 797 [=, &name](const BucketRanges* ranges)->HistogramBase* { |
717 | 798 return new BooleanHistogram(name, ranges); |
718 BooleanHistogram* tentative_histogram = | 799 }, |
719 new BooleanHistogram(name, registered_ranges); | 800 [=](HistogramBase* histogram) {}, |
720 | 801 BOOLEAN_HISTOGRAM, name, 1, 2, 3, flags); |
721 tentative_histogram->SetFlags(flags); | |
722 histogram = | |
723 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); | |
724 } | |
725 | |
726 DCHECK_EQ(BOOLEAN_HISTOGRAM, histogram->GetHistogramType()); | |
727 return histogram; | |
728 } | 802 } |
729 | 803 |
730 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32 flags) { | 804 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32 flags) { |
731 return FactoryGet(std::string(name), flags); | 805 return FactoryGet(std::string(name), flags); |
732 } | 806 } |
733 | 807 |
734 HistogramType BooleanHistogram::GetHistogramType() const { | 808 HistogramType BooleanHistogram::GetHistogramType() const { |
735 return BOOLEAN_HISTOGRAM; | 809 return BOOLEAN_HISTOGRAM; |
736 } | 810 } |
737 | 811 |
738 BooleanHistogram::BooleanHistogram(const std::string& name, | 812 BooleanHistogram::BooleanHistogram(const std::string& name, |
739 const BucketRanges* ranges) | 813 const BucketRanges* ranges) |
740 : LinearHistogram(name, 1, 2, ranges) {} | 814 : LinearHistogram(name, 1, 2, ranges) {} |
741 | 815 |
| 816 BooleanHistogram::BooleanHistogram(const std::string& name, |
| 817 const BucketRanges* ranges, |
| 818 HistogramBase::AtomicCount* counts, |
| 819 HistogramSamples::Metadata* meta) |
| 820 : LinearHistogram(name, 1, 2, ranges, counts, 2, meta) {} |
| 821 |
742 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { | 822 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { |
743 std::string histogram_name; | 823 std::string histogram_name; |
744 int flags; | 824 int flags; |
745 int declared_min; | 825 int declared_min; |
746 int declared_max; | 826 int declared_max; |
747 size_t bucket_count; | 827 size_t bucket_count; |
748 uint32 range_checksum; | 828 uint32 range_checksum; |
749 | 829 |
750 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, | 830 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, |
751 &declared_max, &bucket_count, &range_checksum)) { | 831 &declared_max, &bucket_count, &range_checksum)) { |
(...skipping 12 matching lines...) Expand all Loading... |
764 //------------------------------------------------------------------------------ | 844 //------------------------------------------------------------------------------ |
765 // CustomHistogram: | 845 // CustomHistogram: |
766 //------------------------------------------------------------------------------ | 846 //------------------------------------------------------------------------------ |
767 | 847 |
768 HistogramBase* CustomHistogram::FactoryGet( | 848 HistogramBase* CustomHistogram::FactoryGet( |
769 const std::string& name, | 849 const std::string& name, |
770 const std::vector<Sample>& custom_ranges, | 850 const std::vector<Sample>& custom_ranges, |
771 int32 flags) { | 851 int32 flags) { |
772 CHECK(ValidateCustomRanges(custom_ranges)); | 852 CHECK(ValidateCustomRanges(custom_ranges)); |
773 | 853 |
774 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); | 854 return Histogram::FactoryGet( |
775 if (!histogram) { | 855 [&]()->BucketRanges* { |
776 BucketRanges* ranges = CreateBucketRangesFromCustomRanges(custom_ranges); | 856 // Remove the duplicates in the custom ranges array. |
777 const BucketRanges* registered_ranges = | 857 std::vector<int> ranges = custom_ranges; |
778 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); | 858 ranges.push_back(0); // Ensure we have a zero value. |
| 859 ranges.push_back(HistogramBase::kSampleType_MAX); |
| 860 std::sort(ranges.begin(), ranges.end()); |
| 861 ranges.erase(std::unique(ranges.begin(), ranges.end()), ranges.end()); |
779 | 862 |
780 // To avoid racy destruction at shutdown, the following will be leaked. | 863 BucketRanges* bucket_ranges = new BucketRanges(ranges.size()); |
781 CustomHistogram* tentative_histogram = | 864 for (size_t i = 0; i < ranges.size(); i++) { |
782 new CustomHistogram(name, registered_ranges); | 865 bucket_ranges->set_range(i, ranges[i]); |
783 | 866 } |
784 tentative_histogram->SetFlags(flags); | 867 bucket_ranges->ResetChecksum(); |
785 | 868 return bucket_ranges; |
786 histogram = | 869 }, |
787 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); | 870 [=, &name](const BucketRanges* ranges)->HistogramBase* { |
788 } | 871 return new CustomHistogram(name, ranges); |
789 | 872 }, |
790 DCHECK_EQ(histogram->GetHistogramType(), CUSTOM_HISTOGRAM); | 873 [=](HistogramBase* histogram) {}, |
791 return histogram; | 874 CUSTOM_HISTOGRAM, name, 0, 0, 0, flags); |
792 } | 875 } |
793 | 876 |
794 HistogramBase* CustomHistogram::FactoryGet( | 877 HistogramBase* CustomHistogram::FactoryGet( |
795 const char* name, | 878 const char* name, |
796 const std::vector<Sample>& custom_ranges, | 879 const std::vector<Sample>& custom_ranges, |
797 int32 flags) { | 880 int32 flags) { |
798 return FactoryGet(std::string(name), custom_ranges, flags); | 881 return FactoryGet(std::string(name), custom_ranges, flags); |
799 } | 882 } |
800 | 883 |
801 HistogramType CustomHistogram::GetHistogramType() const { | 884 HistogramType CustomHistogram::GetHistogramType() const { |
(...skipping 15 matching lines...) Expand all Loading... |
817 return all_values; | 900 return all_values; |
818 } | 901 } |
819 | 902 |
820 CustomHistogram::CustomHistogram(const std::string& name, | 903 CustomHistogram::CustomHistogram(const std::string& name, |
821 const BucketRanges* ranges) | 904 const BucketRanges* ranges) |
822 : Histogram(name, | 905 : Histogram(name, |
823 ranges->range(1), | 906 ranges->range(1), |
824 ranges->range(ranges->bucket_count() - 1), | 907 ranges->range(ranges->bucket_count() - 1), |
825 ranges) {} | 908 ranges) {} |
826 | 909 |
| 910 CustomHistogram::CustomHistogram(const std::string& name, |
| 911 const BucketRanges* ranges, |
| 912 HistogramBase::AtomicCount* counts, |
| 913 size_t counts_size, |
| 914 HistogramSamples::Metadata* meta) |
| 915 : Histogram(name, |
| 916 ranges->range(1), |
| 917 ranges->range(ranges->bucket_count() - 1), |
| 918 ranges, |
| 919 counts, |
| 920 counts_size, |
| 921 meta) {} |
| 922 |
827 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { | 923 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { |
828 if (!Histogram::SerializeInfoImpl(pickle)) | 924 if (!Histogram::SerializeInfoImpl(pickle)) |
829 return false; | 925 return false; |
830 | 926 |
831 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't | 927 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't |
832 // write them. | 928 // write them. |
833 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { | 929 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { |
834 if (!pickle->WriteInt(bucket_ranges()->range(i))) | 930 if (!pickle->WriteInt(bucket_ranges()->range(i))) |
835 return false; | 931 return false; |
836 } | 932 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
879 for (size_t i = 0; i < custom_ranges.size(); i++) { | 975 for (size_t i = 0; i < custom_ranges.size(); i++) { |
880 Sample sample = custom_ranges[i]; | 976 Sample sample = custom_ranges[i]; |
881 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) | 977 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) |
882 return false; | 978 return false; |
883 if (sample != 0) | 979 if (sample != 0) |
884 has_valid_range = true; | 980 has_valid_range = true; |
885 } | 981 } |
886 return has_valid_range; | 982 return has_valid_range; |
887 } | 983 } |
888 | 984 |
889 // static | |
890 BucketRanges* CustomHistogram::CreateBucketRangesFromCustomRanges( | |
891 const std::vector<Sample>& custom_ranges) { | |
892 // Remove the duplicates in the custom ranges array. | |
893 std::vector<int> ranges = custom_ranges; | |
894 ranges.push_back(0); // Ensure we have a zero value. | |
895 ranges.push_back(HistogramBase::kSampleType_MAX); | |
896 std::sort(ranges.begin(), ranges.end()); | |
897 ranges.erase(std::unique(ranges.begin(), ranges.end()), ranges.end()); | |
898 | |
899 BucketRanges* bucket_ranges = new BucketRanges(ranges.size()); | |
900 for (size_t i = 0; i < ranges.size(); i++) { | |
901 bucket_ranges->set_range(i, ranges[i]); | |
902 } | |
903 bucket_ranges->ResetChecksum(); | |
904 return bucket_ranges; | |
905 } | |
906 | |
907 } // namespace base | 985 } // namespace base |
OLD | NEW |