Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(257)

Side by Side Diff: base/metrics/histogram.cc

Issue 1425533011: Support "shared" histograms between processes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@shmem-alloc
Patch Set: addressed review comments by Alexei Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/metrics/histogram_macros.h" 20 #include "base/metrics/histogram_macros.h"
21 #include "base/metrics/histogram_persistence.h"
21 #include "base/metrics/metrics_hashes.h" 22 #include "base/metrics/metrics_hashes.h"
23 #include "base/metrics/persistent_memory_allocator.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 {
31 33
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
88
89 class Histogram::Factory {
90 public:
91 Factory(const std::string& name,
92 HistogramBase::Sample minimum,
93 HistogramBase::Sample maximum,
94 size_t bucket_count,
95 int32 flags)
96 : Factory(name, HISTOGRAM, minimum, maximum, bucket_count, flags) {}
97
98 HistogramBase* Build();
99
100 protected:
101 Factory(const std::string& name,
102 HistogramType histogram_type,
103 HistogramBase::Sample minimum,
104 HistogramBase::Sample maximum,
105 size_t bucket_count,
106 int32 flags)
107 : name_(name),
108 histogram_type_(histogram_type),
109 minimum_(minimum),
110 maximum_(maximum),
111 bucket_count_(bucket_count),
112 flags_(flags) {}
113
114 // Create a BucketRanges structure appropriate for this histogram.
115 virtual BucketRanges* CreateRanges() {
116 BucketRanges* ranges = new BucketRanges(bucket_count_ + 1);
117 Histogram::InitializeBucketRanges(minimum_, maximum_, ranges);
118 return ranges;
119 }
120
121 // Allocate the correct Histogram object off the heap (in case persistent
122 // memory is not available).
123 virtual HistogramBase* HeapAlloc(const BucketRanges* ranges) {
124 return new Histogram(name_, minimum_, maximum_, ranges);
125 }
126
127 // Perform any required datafill on the just-created histogram. If
128 // overridden, be sure to call the "super" version.
129 virtual void FillHistogram(HistogramBase* histogram) {
130 histogram->SetFlags(flags_);
131 }
132
133 // These values are protected (instead of private) because they need to
134 // be accessible to methods of sub-classes in order to avoid passing
135 // unnecessary parameters everywhere.
136 const std::string& name_;
137 const HistogramType histogram_type_;
138 HistogramBase::Sample minimum_;
139 HistogramBase::Sample maximum_;
140 size_t bucket_count_;
141 int32 flags_;
142
143 private:
144 DISALLOW_COPY_AND_ASSIGN(Factory);
145 };
146
147 HistogramBase* Histogram::Factory::Build() {
148 ImportPersistentHistograms();
149
150 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name_);
151 if (!histogram) {
152 // To avoid racy destruction at shutdown, the following will be leaked.
153 const BucketRanges* created_ranges = CreateRanges();
154 const BucketRanges* registered_ranges =
155 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(created_ranges);
156
157 // Sometimes the bucket info is dynamically determined in CreateRanges().
158 if (bucket_count_ == 0) {
159 bucket_count_ = registered_ranges->bucket_count();
160 minimum_ = registered_ranges->range(1);
161 maximum_ = registered_ranges->range(bucket_count_ - 1);
162 }
163
164 PersistentMemoryAllocator::Reference histogram_ref = 0;
165 HistogramBase* tentative_histogram = nullptr;
166 PersistentMemoryAllocator* allocator =
167 GetPersistentHistogramMemoryAllocator();
168 if (allocator) {
169 flags_ |= HistogramBase::kIsPersistent;
170 tentative_histogram = AllocatePersistentHistogram(
171 allocator,
172 histogram_type_,
173 name_,
174 minimum_,
175 maximum_,
176 registered_ranges,
177 flags_,
178 &histogram_ref);
179 }
180
181 // Handle the case where no persistent allocator is present or the
182 // persistent allocation fails (perhaps because it is full).
183 if (!tentative_histogram) {
184 DCHECK(!histogram_ref); // Should never have been set.
185 DCHECK(!allocator); // Shouldn't have failed.
186 flags_ &= ~HistogramBase::kIsPersistent;
187 tentative_histogram = HeapAlloc(registered_ranges);
188 }
189
190 FillHistogram(tentative_histogram);
191 histogram =
192 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
193
194 // Persistent histograms need some follow-up processing.
195 if (histogram_ref) {
196 FinalizePersistentHistogram(histogram_ref,
197 histogram == tentative_histogram);
198 }
199 }
200
201 DCHECK_EQ(histogram_type_, histogram->GetHistogramType());
202 if (bucket_count_ != 0 &&
203 !histogram->HasConstructionArguments(minimum_, maximum_, bucket_count_)) {
204 // The construction arguments do not match the existing histogram. This can
205 // come about if an extension updates in the middle of a chrome run and has
206 // changed one of them, or simply by bad code within Chrome itself. We
207 // return NULL here with the expectation that bad code in Chrome will crash
208 // on dereference, but extension/Pepper APIs will guard against NULL and not
209 // crash.
210 DLOG(ERROR) << "Histogram " << name_ << " has bad construction arguments";
211 return nullptr;
212 }
213 return histogram;
214 }
215
216
86 HistogramBase* Histogram::FactoryGet(const std::string& name, 217 HistogramBase* Histogram::FactoryGet(const std::string& name,
87 Sample minimum, 218 Sample minimum,
88 Sample maximum, 219 Sample maximum,
89 size_t bucket_count, 220 size_t bucket_count,
90 int32 flags) { 221 int32 flags) {
91 bool valid_arguments = 222 bool valid_arguments =
92 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count); 223 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count);
93 DCHECK(valid_arguments); 224 DCHECK(valid_arguments);
94 225
95 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 226 return Factory(name, minimum, maximum, bucket_count, flags).Build();
96 if (!histogram) {
97 // To avoid racy destruction at shutdown, the following will be leaked.
98 BucketRanges* ranges = new BucketRanges(bucket_count + 1);
99 InitializeBucketRanges(minimum, maximum, ranges);
100 const BucketRanges* registered_ranges =
101 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
102
103 Histogram* tentative_histogram =
104 new Histogram(name, minimum, maximum, registered_ranges);
105
106 tentative_histogram->SetFlags(flags);
107 histogram =
108 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
109 }
110
111 DCHECK_EQ(HISTOGRAM, histogram->GetHistogramType());
112 if (!histogram->HasConstructionArguments(minimum, maximum, bucket_count)) {
113 // 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
115 // 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
117 // on dereference, but extension/Pepper APIs will guard against NULL and not
118 // crash.
119 DLOG(ERROR) << "Histogram " << name << " has bad construction arguments";
120 return NULL;
121 }
122 return histogram;
123 } 227 }
124 228
125 HistogramBase* Histogram::FactoryTimeGet(const std::string& name, 229 HistogramBase* Histogram::FactoryTimeGet(const std::string& name,
126 TimeDelta minimum, 230 TimeDelta minimum,
127 TimeDelta maximum, 231 TimeDelta maximum,
128 size_t bucket_count, 232 size_t bucket_count,
129 int32 flags) { 233 int32 flags) {
130 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()), 234 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()),
131 static_cast<Sample>(maximum.InMilliseconds()), bucket_count, 235 static_cast<Sample>(maximum.InMilliseconds()), bucket_count,
132 flags); 236 flags);
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 Sample maximum, 440 Sample maximum,
337 const BucketRanges* ranges) 441 const BucketRanges* ranges)
338 : HistogramBase(name), 442 : HistogramBase(name),
339 bucket_ranges_(ranges), 443 bucket_ranges_(ranges),
340 declared_min_(minimum), 444 declared_min_(minimum),
341 declared_max_(maximum) { 445 declared_max_(maximum) {
342 if (ranges) 446 if (ranges)
343 samples_.reset(new SampleVector(HashMetricName(name), ranges)); 447 samples_.reset(new SampleVector(HashMetricName(name), ranges));
344 } 448 }
345 449
450 Histogram::Histogram(const std::string& name,
451 Sample minimum,
452 Sample maximum,
453 const BucketRanges* ranges,
454 HistogramBase::AtomicCount* counts,
455 size_t counts_size,
456 HistogramSamples::Metadata* meta)
457 : HistogramBase(name),
458 bucket_ranges_(ranges),
459 declared_min_(minimum),
460 declared_max_(maximum) {
461 if (ranges)
462 samples_.reset(new SampleVector(HashMetricName(name),
463 counts, counts_size, meta, ranges));
464 }
465
346 Histogram::~Histogram() { 466 Histogram::~Histogram() {
347 } 467 }
348 468
349 bool Histogram::PrintEmptyBucket(size_t index) const { 469 bool Histogram::PrintEmptyBucket(size_t index) const {
350 return true; 470 return true;
351 } 471 }
352 472
353 // Use the actual bucket widths (like a linear histogram) until the widths get 473 // 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 474 // 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 475 // get so big so fast (and we don't expect to see a lot of entries in the large
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 ++index; 657 ++index;
538 } 658 }
539 } 659 }
540 } 660 }
541 661
542 //------------------------------------------------------------------------------ 662 //------------------------------------------------------------------------------
543 // LinearHistogram: This histogram uses a traditional set of evenly spaced 663 // LinearHistogram: This histogram uses a traditional set of evenly spaced
544 // buckets. 664 // buckets.
545 //------------------------------------------------------------------------------ 665 //------------------------------------------------------------------------------
546 666
667 class LinearHistogram::Factory : public Histogram::Factory {
668 public:
669 Factory(const std::string& name,
670 HistogramBase::Sample minimum,
671 HistogramBase::Sample maximum,
672 size_t bucket_count,
673 int32 flags,
674 const DescriptionPair* descriptions)
675 : Histogram::Factory(name, LINEAR_HISTOGRAM, minimum, maximum,
676 bucket_count, flags) {
677 descriptions_ = descriptions;
678 }
679
680 protected:
681 BucketRanges* CreateRanges() override {
682 BucketRanges* ranges = new BucketRanges(bucket_count_ + 1);
683 LinearHistogram::InitializeBucketRanges(minimum_, maximum_, ranges);
684 return ranges;
685 }
686
687 HistogramBase* HeapAlloc(const BucketRanges* ranges) override {
688 return new LinearHistogram(name_, minimum_, maximum_, ranges);
689 }
690
691 void FillHistogram(HistogramBase* base_histogram) override {
692 Histogram::Factory::FillHistogram(base_histogram);
693 LinearHistogram* histogram = static_cast<LinearHistogram*>(base_histogram);
694 // Set range descriptions.
695 if (descriptions_) {
696 for (int i = 0; descriptions_[i].description; ++i) {
697 histogram->bucket_description_[descriptions_[i].sample] =
698 descriptions_[i].description;
699 }
700 }
701 }
702
703 private:
704 const DescriptionPair* descriptions_;
705 DISALLOW_COPY_AND_ASSIGN(Factory);
706 };
707
547 LinearHistogram::~LinearHistogram() {} 708 LinearHistogram::~LinearHistogram() {}
548 709
549 HistogramBase* LinearHistogram::FactoryGet(const std::string& name, 710 HistogramBase* LinearHistogram::FactoryGet(const std::string& name,
550 Sample minimum, 711 Sample minimum,
551 Sample maximum, 712 Sample maximum,
552 size_t bucket_count, 713 size_t bucket_count,
553 int32 flags) { 714 int32 flags) {
554 return FactoryGetWithRangeDescription( 715 return FactoryGetWithRangeDescription(
555 name, minimum, maximum, bucket_count, flags, NULL); 716 name, minimum, maximum, bucket_count, flags, NULL);
556 } 717 }
(...skipping 29 matching lines...) Expand all
586 const std::string& name, 747 const std::string& name,
587 Sample minimum, 748 Sample minimum,
588 Sample maximum, 749 Sample maximum,
589 size_t bucket_count, 750 size_t bucket_count,
590 int32 flags, 751 int32 flags,
591 const DescriptionPair descriptions[]) { 752 const DescriptionPair descriptions[]) {
592 bool valid_arguments = Histogram::InspectConstructionArguments( 753 bool valid_arguments = Histogram::InspectConstructionArguments(
593 name, &minimum, &maximum, &bucket_count); 754 name, &minimum, &maximum, &bucket_count);
594 DCHECK(valid_arguments); 755 DCHECK(valid_arguments);
595 756
596 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 757 return Factory(name, minimum, maximum, bucket_count, flags, descriptions)
597 if (!histogram) { 758 .Build();
598 // To avoid racy destruction at shutdown, the following will be leaked.
599 BucketRanges* ranges = new BucketRanges(bucket_count + 1);
600 InitializeBucketRanges(minimum, maximum, ranges);
601 const BucketRanges* registered_ranges =
602 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
603
604 LinearHistogram* tentative_histogram =
605 new LinearHistogram(name, minimum, maximum, registered_ranges);
606
607 // Set range descriptions.
608 if (descriptions) {
609 for (int i = 0; descriptions[i].description; ++i) {
610 tentative_histogram->bucket_description_[descriptions[i].sample] =
611 descriptions[i].description;
612 }
613 }
614
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 } 759 }
633 760
634 HistogramType LinearHistogram::GetHistogramType() const { 761 HistogramType LinearHistogram::GetHistogramType() const {
635 return LINEAR_HISTOGRAM; 762 return LINEAR_HISTOGRAM;
636 } 763 }
637 764
638 LinearHistogram::LinearHistogram(const std::string& name, 765 LinearHistogram::LinearHistogram(const std::string& name,
639 Sample minimum, 766 Sample minimum,
640 Sample maximum, 767 Sample maximum,
641 const BucketRanges* ranges) 768 const BucketRanges* ranges)
642 : Histogram(name, minimum, maximum, ranges) { 769 : Histogram(name, minimum, maximum, ranges) {
643 } 770 }
644 771
772 LinearHistogram::LinearHistogram(const std::string& name,
773 Sample minimum,
774 Sample maximum,
775 const BucketRanges* ranges,
776 HistogramBase::AtomicCount* counts,
777 size_t counts_size,
778 HistogramSamples::Metadata* meta)
779 : Histogram(name,
780 minimum,
781 maximum,
782 ranges,
783 counts,
784 counts_size,
785 meta) {}
786
645 double LinearHistogram::GetBucketSize(Count current, size_t i) const { 787 double LinearHistogram::GetBucketSize(Count current, size_t i) const {
646 DCHECK_GT(ranges(i + 1), ranges(i)); 788 DCHECK_GT(ranges(i + 1), ranges(i));
647 // Adjacent buckets with different widths would have "surprisingly" many (few) 789 // Adjacent buckets with different widths would have "surprisingly" many (few)
648 // samples in a histogram if we didn't normalize this way. 790 // samples in a histogram if we didn't normalize this way.
649 double denominator = ranges(i + 1) - ranges(i); 791 double denominator = ranges(i + 1) - ranges(i);
650 return current/denominator; 792 return current/denominator;
651 } 793 }
652 794
653 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const { 795 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const {
654 int range = ranges(i); 796 int range = ranges(i);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 // The serialized histogram might be corrupted. 840 // The serialized histogram might be corrupted.
699 return NULL; 841 return NULL;
700 } 842 }
701 return histogram; 843 return histogram;
702 } 844 }
703 845
704 //------------------------------------------------------------------------------ 846 //------------------------------------------------------------------------------
705 // This section provides implementation for BooleanHistogram. 847 // This section provides implementation for BooleanHistogram.
706 //------------------------------------------------------------------------------ 848 //------------------------------------------------------------------------------
707 849
850 class BooleanHistogram::Factory : public Histogram::Factory {
851 public:
852 Factory(const std::string& name, int32 flags)
853 : Histogram::Factory(name, BOOLEAN_HISTOGRAM, 1, 2, 3, flags) {}
854
855 protected:
856 BucketRanges* CreateRanges() {
857 BucketRanges* ranges = new BucketRanges(3 + 1);
858 LinearHistogram::InitializeBucketRanges(1, 2, ranges);
859 return ranges;
860 }
861
862 HistogramBase* HeapAlloc(const BucketRanges* ranges) override {
863 return new BooleanHistogram(name_, ranges);
864 }
865
866 private:
867 DISALLOW_COPY_AND_ASSIGN(Factory);
868 };
869
708 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name, 870 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name,
709 int32 flags) { 871 int32 flags) {
710 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 872 return Factory(name, flags).Build();
711 if (!histogram) {
712 // To avoid racy destruction at shutdown, the following will be leaked.
713 BucketRanges* ranges = new BucketRanges(4);
714 LinearHistogram::InitializeBucketRanges(1, 2, ranges);
715 const BucketRanges* registered_ranges =
716 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
717
718 BooleanHistogram* tentative_histogram =
719 new BooleanHistogram(name, registered_ranges);
720
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 } 873 }
729 874
730 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32 flags) { 875 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32 flags) {
731 return FactoryGet(std::string(name), flags); 876 return FactoryGet(std::string(name), flags);
732 } 877 }
733 878
734 HistogramType BooleanHistogram::GetHistogramType() const { 879 HistogramType BooleanHistogram::GetHistogramType() const {
735 return BOOLEAN_HISTOGRAM; 880 return BOOLEAN_HISTOGRAM;
736 } 881 }
737 882
738 BooleanHistogram::BooleanHistogram(const std::string& name, 883 BooleanHistogram::BooleanHistogram(const std::string& name,
739 const BucketRanges* ranges) 884 const BucketRanges* ranges)
740 : LinearHistogram(name, 1, 2, ranges) {} 885 : LinearHistogram(name, 1, 2, ranges) {}
741 886
887 BooleanHistogram::BooleanHistogram(const std::string& name,
888 const BucketRanges* ranges,
889 HistogramBase::AtomicCount* counts,
890 HistogramSamples::Metadata* meta)
891 : LinearHistogram(name, 1, 2, ranges, counts, 2, meta) {}
892
742 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { 893 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) {
743 std::string histogram_name; 894 std::string histogram_name;
744 int flags; 895 int flags;
745 int declared_min; 896 int declared_min;
746 int declared_max; 897 int declared_max;
747 size_t bucket_count; 898 size_t bucket_count;
748 uint32 range_checksum; 899 uint32 range_checksum;
749 900
750 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, 901 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min,
751 &declared_max, &bucket_count, &range_checksum)) { 902 &declared_max, &bucket_count, &range_checksum)) {
752 return NULL; 903 return NULL;
753 } 904 }
754 905
755 HistogramBase* histogram = BooleanHistogram::FactoryGet( 906 HistogramBase* histogram = BooleanHistogram::FactoryGet(
756 histogram_name, flags); 907 histogram_name, flags);
757 if (!ValidateRangeChecksum(*histogram, range_checksum)) { 908 if (!ValidateRangeChecksum(*histogram, range_checksum)) {
758 // The serialized histogram might be corrupted. 909 // The serialized histogram might be corrupted.
759 return NULL; 910 return NULL;
760 } 911 }
761 return histogram; 912 return histogram;
762 } 913 }
763 914
764 //------------------------------------------------------------------------------ 915 //------------------------------------------------------------------------------
765 // CustomHistogram: 916 // CustomHistogram:
766 //------------------------------------------------------------------------------ 917 //------------------------------------------------------------------------------
767 918
919 class CustomHistogram::Factory : public Histogram::Factory {
920 public:
921 Factory(const std::string& name,
922 const std::vector<Sample>* custom_ranges,
923 int32 flags)
924 : Histogram::Factory(name, CUSTOM_HISTOGRAM, 0, 0, 0, flags) {
925 custom_ranges_ = custom_ranges;
926 }
927
928 protected:
929 BucketRanges* CreateRanges() {
930 // Remove the duplicates in the custom ranges array.
931 std::vector<int> ranges = *custom_ranges_;
932 ranges.push_back(0); // Ensure we have a zero value.
933 ranges.push_back(HistogramBase::kSampleType_MAX);
934 std::sort(ranges.begin(), ranges.end());
935 ranges.erase(std::unique(ranges.begin(), ranges.end()), ranges.end());
936
937 BucketRanges* bucket_ranges = new BucketRanges(ranges.size());
938 for (size_t i = 0; i < ranges.size(); i++) {
939 bucket_ranges->set_range(i, ranges[i]);
940 }
941 bucket_ranges->ResetChecksum();
942 return bucket_ranges;
943 }
944
945 HistogramBase* HeapAlloc(const BucketRanges* ranges) override {
946 return new CustomHistogram(name_, ranges);
947 }
948
949 private:
950 const std::vector<Sample>* custom_ranges_;
951 DISALLOW_COPY_AND_ASSIGN(Factory);
Alexei Svitkine (slow) 2016/01/08 18:52:48 Nit: Add a blank line above this. Same for the oth
bcwhite 2016/01/12 16:34:57 Done.
952 };
953
768 HistogramBase* CustomHistogram::FactoryGet( 954 HistogramBase* CustomHistogram::FactoryGet(
769 const std::string& name, 955 const std::string& name,
770 const std::vector<Sample>& custom_ranges, 956 const std::vector<Sample>& custom_ranges,
771 int32 flags) { 957 int32 flags) {
772 CHECK(ValidateCustomRanges(custom_ranges)); 958 CHECK(ValidateCustomRanges(custom_ranges));
773 959
774 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 960 return Factory(name, &custom_ranges, flags).Build();
775 if (!histogram) {
776 BucketRanges* ranges = CreateBucketRangesFromCustomRanges(custom_ranges);
777 const BucketRanges* registered_ranges =
778 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
779
780 // To avoid racy destruction at shutdown, the following will be leaked.
781 CustomHistogram* tentative_histogram =
782 new CustomHistogram(name, registered_ranges);
783
784 tentative_histogram->SetFlags(flags);
785
786 histogram =
787 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
788 }
789
790 DCHECK_EQ(histogram->GetHistogramType(), CUSTOM_HISTOGRAM);
791 return histogram;
792 } 961 }
793 962
794 HistogramBase* CustomHistogram::FactoryGet( 963 HistogramBase* CustomHistogram::FactoryGet(
795 const char* name, 964 const char* name,
796 const std::vector<Sample>& custom_ranges, 965 const std::vector<Sample>& custom_ranges,
797 int32 flags) { 966 int32 flags) {
798 return FactoryGet(std::string(name), custom_ranges, flags); 967 return FactoryGet(std::string(name), custom_ranges, flags);
799 } 968 }
800 969
801 HistogramType CustomHistogram::GetHistogramType() const { 970 HistogramType CustomHistogram::GetHistogramType() const {
(...skipping 15 matching lines...) Expand all
817 return all_values; 986 return all_values;
818 } 987 }
819 988
820 CustomHistogram::CustomHistogram(const std::string& name, 989 CustomHistogram::CustomHistogram(const std::string& name,
821 const BucketRanges* ranges) 990 const BucketRanges* ranges)
822 : Histogram(name, 991 : Histogram(name,
823 ranges->range(1), 992 ranges->range(1),
824 ranges->range(ranges->bucket_count() - 1), 993 ranges->range(ranges->bucket_count() - 1),
825 ranges) {} 994 ranges) {}
826 995
996 CustomHistogram::CustomHistogram(const std::string& name,
997 const BucketRanges* ranges,
998 HistogramBase::AtomicCount* counts,
999 size_t counts_size,
1000 HistogramSamples::Metadata* meta)
1001 : Histogram(name,
1002 ranges->range(1),
1003 ranges->range(ranges->bucket_count() - 1),
1004 ranges,
1005 counts,
1006 counts_size,
1007 meta) {}
1008
827 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { 1009 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const {
828 if (!Histogram::SerializeInfoImpl(pickle)) 1010 if (!Histogram::SerializeInfoImpl(pickle))
829 return false; 1011 return false;
830 1012
831 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't 1013 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't
832 // write them. 1014 // write them.
833 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { 1015 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) {
834 if (!pickle->WriteInt(bucket_ranges()->range(i))) 1016 if (!pickle->WriteInt(bucket_ranges()->range(i)))
835 return false; 1017 return false;
836 } 1018 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
879 for (size_t i = 0; i < custom_ranges.size(); i++) { 1061 for (size_t i = 0; i < custom_ranges.size(); i++) {
880 Sample sample = custom_ranges[i]; 1062 Sample sample = custom_ranges[i];
881 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) 1063 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1)
882 return false; 1064 return false;
883 if (sample != 0) 1065 if (sample != 0)
884 has_valid_range = true; 1066 has_valid_range = true;
885 } 1067 }
886 return has_valid_range; 1068 return has_valid_range;
887 } 1069 }
888 1070
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 1071 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698