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

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: change from lambdas to Factory classes for creating histograms with common code 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/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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 bool ValidateRangeChecksum(const HistogramBase& histogram, 72 bool ValidateRangeChecksum(const HistogramBase& histogram,
71 uint32 range_checksum) { 73 uint32 range_checksum) {
72 const Histogram& casted_histogram = 74 const Histogram& casted_histogram =
73 static_cast<const Histogram&>(histogram); 75 static_cast<const Histogram&>(histogram);
74 76
75 return casted_histogram.bucket_ranges()->checksum() == range_checksum; 77 return casted_histogram.bucket_ranges()->checksum() == range_checksum;
76 } 78 }
77 79
78 } // namespace 80 } // namespace
79 81
82
83 class Histogram::Factory {
84 public:
85 Factory(const std::string& name,
86 HistogramBase::Sample minimum,
87 HistogramBase::Sample maximum,
88 size_t bucket_count,
89 int32 flags)
90 : Factory(name, HISTOGRAM, minimum, maximum, bucket_count, flags) {}
91
92 HistogramBase* Build();
93
94 protected:
95 Factory(const std::string& name,
96 HistogramType histogram_type,
97 HistogramBase::Sample minimum,
98 HistogramBase::Sample maximum,
99 size_t bucket_count,
100 int32 flags)
101 : name_(name),
102 histogram_type_(histogram_type),
103 minimum_(minimum),
104 maximum_(maximum),
105 bucket_count_(bucket_count),
106 flags_(flags) {}
107
108 virtual BucketRanges* CreateRanges();
109 virtual HistogramBase* HeapAlloc(const BucketRanges* ranges);
110 virtual void FillHistogram(HistogramBase* histogram);
111
112 const std::string& name_;
113 const HistogramType histogram_type_;
114 HistogramBase::Sample minimum_;
115 HistogramBase::Sample maximum_;
116 size_t bucket_count_;
117 int32 flags_;
Alexei Svitkine (slow) 2015/12/15 23:03:37 Do these need to be members or could they be param
bcwhite 2015/12/16 13:36:34 Whether the defaults are set in the ctor or as par
Alexei Svitkine (slow) 2015/12/16 16:33:49 Sorry, I didn't mention it, but one of the reason
bcwhite 2015/12/17 15:55:48 I think given that the class is a utility class co
118 };
119
120 HistogramBase* Histogram::Factory::Build() {
121 ImportPersistentHistograms();
122
123 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name_);
124 if (!histogram) {
125 // To avoid racy destruction at shutdown, the following will be leaked.
126 const BucketRanges* created_ranges = CreateRanges();
127 const BucketRanges* registered_ranges =
128 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(created_ranges);
129
130 // Sometimes the bucket info is dynamically determined in create_ranges().
131 if (bucket_count_ == 0) {
132 bucket_count_ = registered_ranges->bucket_count();
133 minimum_ = registered_ranges->range(1);
134 maximum_ = registered_ranges->range(bucket_count_ - 1);
135 }
136
137 PersistentMemoryAllocator::Reference histogram_ref = 0;
138 HistogramBase* tentative_histogram = nullptr;
139 PersistentMemoryAllocator* allocator =
140 GetPersistentHistogramMemoryAllocator();
141 if (allocator) {
142 flags_ |= HistogramBase::kIsPersistent;
143 tentative_histogram = AllocatePersistentHistogram(
144 allocator,
145 histogram_type_,
146 name_,
147 minimum_,
148 maximum_,
149 registered_ranges,
150 flags_,
151 &histogram_ref);
152 }
153 if (!tentative_histogram) {
154 flags_ &= ~HistogramBase::kIsPersistent;
155 tentative_histogram = HeapAlloc(registered_ranges);
156 }
157
158 FillHistogram(tentative_histogram);
159
160 tentative_histogram->SetFlags(flags_);
161 histogram =
162 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
163
164 // Persistent histograms need some follow-up processing.
165 if (histogram_ref) {
166 // If the created persistent histogram is canonical then it needs to be
167 // marked as "iterable" in order to be found by other processes.
168 if (histogram == tentative_histogram)
169 GetPersistentHistogramMemoryAllocator()->MakeIterable(histogram_ref);
170 // If it's not the canonical one then a race condition must have caused
171 // two to be created. The allocator does not support releasing the
172 // acquired memory so just change the type to be empty.
173 else
174 GetPersistentHistogramMemoryAllocator()->SetType(histogram_ref, 0);
175 }
176 }
177
178 DCHECK_EQ(histogram_type_, histogram->GetHistogramType());
179 if (bucket_count_ != 0 &&
180 !histogram->HasConstructionArguments(minimum_, maximum_, bucket_count_)) {
181 // The construction arguments do not match the existing histogram. This can
182 // come about if an extension updates in the middle of a chrome run and has
183 // changed one of them, or simply by bad code within Chrome itself. We
184 // return NULL here with the expectation that bad code in Chrome will crash
185 // on dereference, but extension/Pepper APIs will guard against NULL and not
186 // crash.
187 DLOG(ERROR) << "Histogram " << name_ << " has bad construction arguments";
188 return NULL;
Alexei Svitkine (slow) 2015/12/16 16:33:49 Nit: nullptr
bcwhite 2015/12/17 15:55:48 Old habits die hard. Done.
189 }
190 return histogram;
191 }
192
193 BucketRanges* Histogram::Factory::CreateRanges() {
Alexei Svitkine (slow) 2015/12/16 16:33:49 So, thinking about this more.... given that these
bcwhite 2015/12/17 15:55:48 I wouldn't even need a class for that. It would j
194 BucketRanges* ranges = new BucketRanges(bucket_count_ + 1);
195 Histogram::InitializeBucketRanges(minimum_, maximum_, ranges);
196 return ranges;
197 }
198
199 HistogramBase* Histogram::Factory::HeapAlloc(const BucketRanges* ranges) {
200 return new Histogram(name_, minimum_, maximum_, ranges);
201 }
202
203 void Histogram::Factory::FillHistogram(HistogramBase* histogram) {
204 }
205
206
207 class LinearHistogram::Factory : public Histogram::Factory {
208 public:
209 Factory(const std::string& name,
210 HistogramBase::Sample minimum,
211 HistogramBase::Sample maximum,
212 size_t bucket_count,
213 int32 flags,
214 const DescriptionPair* descriptions)
215 : Histogram::Factory(name, LINEAR_HISTOGRAM, minimum, maximum,
216 bucket_count, flags) {
217 descriptions_ = descriptions;
218 }
219
220 protected:
221 BucketRanges* CreateRanges();
222 HistogramBase* HeapAlloc(const BucketRanges* ranges) override;
223 void FillHistogram(HistogramBase* histogram) override;
224
225 const DescriptionPair* descriptions_;
226 };
227
228 BucketRanges* LinearHistogram::Factory::CreateRanges() {
229 BucketRanges* ranges = new BucketRanges(bucket_count_ + 1);
230 LinearHistogram::InitializeBucketRanges(minimum_, maximum_, ranges);
231 return ranges;
232 }
233
234 HistogramBase* LinearHistogram::Factory::HeapAlloc(const BucketRanges* ranges) {
235 return new LinearHistogram(name_, minimum_, maximum_, ranges);
236 }
237
238 void LinearHistogram::Factory::FillHistogram(HistogramBase* base_histogram) {
239 LinearHistogram* histogram = static_cast<LinearHistogram*>(base_histogram);
240 // Set range descriptions.
241 if (descriptions_) {
242 for (int i = 0; descriptions_[i].description; ++i) {
243 histogram->bucket_description_[descriptions_[i].sample] =
244 descriptions_[i].description;
245 }
246 }
247 }
248
249
250 class BooleanHistogram::Factory : public Histogram::Factory {
251 public:
252 Factory(const std::string& name, int32 flags)
253 : Histogram::Factory(name, BOOLEAN_HISTOGRAM, 1, 2, 3, flags) {}
254
255 protected:
256 BucketRanges* CreateRanges();
257 HistogramBase* HeapAlloc(const BucketRanges* ranges) override;
258 };
259
260 BucketRanges* BooleanHistogram::Factory::CreateRanges() {
261 BucketRanges* ranges = new BucketRanges(3 + 1);
262 LinearHistogram::InitializeBucketRanges(1, 2, ranges);
263 return ranges;
264 }
265
266 HistogramBase* BooleanHistogram::Factory::HeapAlloc(
267 const BucketRanges* ranges) {
268 return new BooleanHistogram(name_, ranges);
269 }
270
271
272 class CustomHistogram::Factory : public Histogram::Factory {
273 public:
274 Factory(const std::string& name,
275 const std::vector<Sample>* custom_ranges,
276 int32 flags)
277 : Histogram::Factory(name, CUSTOM_HISTOGRAM, 0, 0, 0, flags) {
278 custom_ranges_ = custom_ranges;
279 }
280
281 protected:
282 BucketRanges* CreateRanges();
283 HistogramBase* HeapAlloc(const BucketRanges* ranges) override;
284
285 const std::vector<Sample>* custom_ranges_;
286 };
287
288 BucketRanges* CustomHistogram::Factory::CreateRanges() {
289 // Remove the duplicates in the custom ranges array.
290 std::vector<int> ranges = *custom_ranges_;
291 ranges.push_back(0); // Ensure we have a zero value.
292 ranges.push_back(HistogramBase::kSampleType_MAX);
293 std::sort(ranges.begin(), ranges.end());
294 ranges.erase(std::unique(ranges.begin(), ranges.end()), ranges.end());
295
296 BucketRanges* bucket_ranges = new BucketRanges(ranges.size());
297 for (size_t i = 0; i < ranges.size(); i++) {
298 bucket_ranges->set_range(i, ranges[i]);
299 }
300 bucket_ranges->ResetChecksum();
301 return bucket_ranges;
302 }
303
304 HistogramBase* CustomHistogram::Factory::HeapAlloc(const BucketRanges* ranges) {
305 return new CustomHistogram(name_, ranges);
306 }
307
308
80 typedef HistogramBase::Count Count; 309 typedef HistogramBase::Count Count;
81 typedef HistogramBase::Sample Sample; 310 typedef HistogramBase::Sample Sample;
82 311
83 // static 312 // static
84 const size_t Histogram::kBucketCount_MAX = 16384u; 313 const size_t Histogram::kBucketCount_MAX = 16384u;
85 314
86 HistogramBase* Histogram::FactoryGet(const std::string& name, 315 HistogramBase* Histogram::FactoryGet(const std::string& name,
87 Sample minimum, 316 Sample minimum,
88 Sample maximum, 317 Sample maximum,
89 size_t bucket_count, 318 size_t bucket_count,
90 int32 flags) { 319 int32 flags) {
91 bool valid_arguments = 320 bool valid_arguments =
92 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count); 321 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count);
93 DCHECK(valid_arguments); 322 DCHECK(valid_arguments);
94 323
95 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 324 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 } 325 }
124 326
125 HistogramBase* Histogram::FactoryTimeGet(const std::string& name, 327 HistogramBase* Histogram::FactoryTimeGet(const std::string& name,
126 TimeDelta minimum, 328 TimeDelta minimum,
127 TimeDelta maximum, 329 TimeDelta maximum,
128 size_t bucket_count, 330 size_t bucket_count,
129 int32 flags) { 331 int32 flags) {
130 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()), 332 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()),
131 static_cast<Sample>(maximum.InMilliseconds()), bucket_count, 333 static_cast<Sample>(maximum.InMilliseconds()), bucket_count,
132 flags); 334 flags);
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 Sample maximum, 538 Sample maximum,
337 const BucketRanges* ranges) 539 const BucketRanges* ranges)
338 : HistogramBase(name), 540 : HistogramBase(name),
339 bucket_ranges_(ranges), 541 bucket_ranges_(ranges),
340 declared_min_(minimum), 542 declared_min_(minimum),
341 declared_max_(maximum) { 543 declared_max_(maximum) {
342 if (ranges) 544 if (ranges)
343 samples_.reset(new SampleVector(HashMetricName(name), ranges)); 545 samples_.reset(new SampleVector(HashMetricName(name), ranges));
344 } 546 }
345 547
548 Histogram::Histogram(const std::string& name,
549 Sample minimum,
550 Sample maximum,
551 const BucketRanges* ranges,
552 HistogramBase::AtomicCount* counts,
553 size_t counts_size,
554 HistogramSamples::Metadata* meta)
555 : HistogramBase(name),
556 bucket_ranges_(ranges),
557 declared_min_(minimum),
558 declared_max_(maximum) {
559 if (ranges)
560 samples_.reset(new SampleVector(HashMetricName(name),
561 counts, counts_size, meta, ranges));
562 }
563
346 Histogram::~Histogram() { 564 Histogram::~Histogram() {
347 } 565 }
348 566
349 bool Histogram::PrintEmptyBucket(size_t index) const { 567 bool Histogram::PrintEmptyBucket(size_t index) const {
350 return true; 568 return true;
351 } 569 }
352 570
353 // Use the actual bucket widths (like a linear histogram) until the widths get 571 // 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 572 // 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 573 // 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
586 const std::string& name, 804 const std::string& name,
587 Sample minimum, 805 Sample minimum,
588 Sample maximum, 806 Sample maximum,
589 size_t bucket_count, 807 size_t bucket_count,
590 int32 flags, 808 int32 flags,
591 const DescriptionPair descriptions[]) { 809 const DescriptionPair descriptions[]) {
592 bool valid_arguments = Histogram::InspectConstructionArguments( 810 bool valid_arguments = Histogram::InspectConstructionArguments(
593 name, &minimum, &maximum, &bucket_count); 811 name, &minimum, &maximum, &bucket_count);
594 DCHECK(valid_arguments); 812 DCHECK(valid_arguments);
595 813
596 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 814 return Factory(name, minimum, maximum, bucket_count, flags, descriptions)
597 if (!histogram) { 815 .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 } 816 }
633 817
634 HistogramType LinearHistogram::GetHistogramType() const { 818 HistogramType LinearHistogram::GetHistogramType() const {
635 return LINEAR_HISTOGRAM; 819 return LINEAR_HISTOGRAM;
636 } 820 }
637 821
638 LinearHistogram::LinearHistogram(const std::string& name, 822 LinearHistogram::LinearHistogram(const std::string& name,
639 Sample minimum, 823 Sample minimum,
640 Sample maximum, 824 Sample maximum,
641 const BucketRanges* ranges) 825 const BucketRanges* ranges)
642 : Histogram(name, minimum, maximum, ranges) { 826 : Histogram(name, minimum, maximum, ranges) {
643 } 827 }
644 828
829 LinearHistogram::LinearHistogram(const std::string& name,
830 Sample minimum,
831 Sample maximum,
832 const BucketRanges* ranges,
833 HistogramBase::AtomicCount* counts,
834 size_t counts_size,
835 HistogramSamples::Metadata* meta)
836 : Histogram(name,
837 minimum,
838 maximum,
839 ranges,
840 counts,
841 counts_size,
842 meta) {}
843
645 double LinearHistogram::GetBucketSize(Count current, size_t i) const { 844 double LinearHistogram::GetBucketSize(Count current, size_t i) const {
646 DCHECK_GT(ranges(i + 1), ranges(i)); 845 DCHECK_GT(ranges(i + 1), ranges(i));
647 // Adjacent buckets with different widths would have "surprisingly" many (few) 846 // Adjacent buckets with different widths would have "surprisingly" many (few)
648 // samples in a histogram if we didn't normalize this way. 847 // samples in a histogram if we didn't normalize this way.
649 double denominator = ranges(i + 1) - ranges(i); 848 double denominator = ranges(i + 1) - ranges(i);
650 return current/denominator; 849 return current/denominator;
651 } 850 }
652 851
653 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const { 852 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const {
654 int range = ranges(i); 853 int range = ranges(i);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 } 899 }
701 return histogram; 900 return histogram;
702 } 901 }
703 902
704 //------------------------------------------------------------------------------ 903 //------------------------------------------------------------------------------
705 // This section provides implementation for BooleanHistogram. 904 // This section provides implementation for BooleanHistogram.
706 //------------------------------------------------------------------------------ 905 //------------------------------------------------------------------------------
707 906
708 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name, 907 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name,
709 int32 flags) { 908 int32 flags) {
710 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 909 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 } 910 }
729 911
730 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32 flags) { 912 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32 flags) {
731 return FactoryGet(std::string(name), flags); 913 return FactoryGet(std::string(name), flags);
732 } 914 }
733 915
734 HistogramType BooleanHistogram::GetHistogramType() const { 916 HistogramType BooleanHistogram::GetHistogramType() const {
735 return BOOLEAN_HISTOGRAM; 917 return BOOLEAN_HISTOGRAM;
736 } 918 }
737 919
738 BooleanHistogram::BooleanHistogram(const std::string& name, 920 BooleanHistogram::BooleanHistogram(const std::string& name,
739 const BucketRanges* ranges) 921 const BucketRanges* ranges)
740 : LinearHistogram(name, 1, 2, ranges) {} 922 : LinearHistogram(name, 1, 2, ranges) {}
741 923
924 BooleanHistogram::BooleanHistogram(const std::string& name,
925 const BucketRanges* ranges,
926 HistogramBase::AtomicCount* counts,
927 HistogramSamples::Metadata* meta)
928 : LinearHistogram(name, 1, 2, ranges, counts, 2, meta) {}
929
742 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { 930 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) {
743 std::string histogram_name; 931 std::string histogram_name;
744 int flags; 932 int flags;
745 int declared_min; 933 int declared_min;
746 int declared_max; 934 int declared_max;
747 size_t bucket_count; 935 size_t bucket_count;
748 uint32 range_checksum; 936 uint32 range_checksum;
749 937
750 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, 938 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min,
751 &declared_max, &bucket_count, &range_checksum)) { 939 &declared_max, &bucket_count, &range_checksum)) {
(...skipping 12 matching lines...) Expand all
764 //------------------------------------------------------------------------------ 952 //------------------------------------------------------------------------------
765 // CustomHistogram: 953 // CustomHistogram:
766 //------------------------------------------------------------------------------ 954 //------------------------------------------------------------------------------
767 955
768 HistogramBase* CustomHistogram::FactoryGet( 956 HistogramBase* CustomHistogram::FactoryGet(
769 const std::string& name, 957 const std::string& name,
770 const std::vector<Sample>& custom_ranges, 958 const std::vector<Sample>& custom_ranges,
771 int32 flags) { 959 int32 flags) {
772 CHECK(ValidateCustomRanges(custom_ranges)); 960 CHECK(ValidateCustomRanges(custom_ranges));
773 961
774 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 962 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 } 963 }
793 964
794 HistogramBase* CustomHistogram::FactoryGet( 965 HistogramBase* CustomHistogram::FactoryGet(
795 const char* name, 966 const char* name,
796 const std::vector<Sample>& custom_ranges, 967 const std::vector<Sample>& custom_ranges,
797 int32 flags) { 968 int32 flags) {
798 return FactoryGet(std::string(name), custom_ranges, flags); 969 return FactoryGet(std::string(name), custom_ranges, flags);
799 } 970 }
800 971
801 HistogramType CustomHistogram::GetHistogramType() const { 972 HistogramType CustomHistogram::GetHistogramType() const {
(...skipping 15 matching lines...) Expand all
817 return all_values; 988 return all_values;
818 } 989 }
819 990
820 CustomHistogram::CustomHistogram(const std::string& name, 991 CustomHistogram::CustomHistogram(const std::string& name,
821 const BucketRanges* ranges) 992 const BucketRanges* ranges)
822 : Histogram(name, 993 : Histogram(name,
823 ranges->range(1), 994 ranges->range(1),
824 ranges->range(ranges->bucket_count() - 1), 995 ranges->range(ranges->bucket_count() - 1),
825 ranges) {} 996 ranges) {}
826 997
998 CustomHistogram::CustomHistogram(const std::string& name,
999 const BucketRanges* ranges,
1000 HistogramBase::AtomicCount* counts,
1001 size_t counts_size,
1002 HistogramSamples::Metadata* meta)
1003 : Histogram(name,
1004 ranges->range(1),
1005 ranges->range(ranges->bucket_count() - 1),
1006 ranges,
1007 counts,
1008 counts_size,
1009 meta) {}
1010
827 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { 1011 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const {
828 if (!Histogram::SerializeInfoImpl(pickle)) 1012 if (!Histogram::SerializeInfoImpl(pickle))
829 return false; 1013 return false;
830 1014
831 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't 1015 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't
832 // write them. 1016 // write them.
833 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { 1017 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) {
834 if (!pickle->WriteInt(bucket_ranges()->range(i))) 1018 if (!pickle->WriteInt(bucket_ranges()->range(i)))
835 return false; 1019 return false;
836 } 1020 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
879 for (size_t i = 0; i < custom_ranges.size(); i++) { 1063 for (size_t i = 0; i < custom_ranges.size(); i++) {
880 Sample sample = custom_ranges[i]; 1064 Sample sample = custom_ranges[i];
881 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) 1065 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1)
882 return false; 1066 return false;
883 if (sample != 0) 1067 if (sample != 0)
884 has_valid_range = true; 1068 has_valid_range = true;
885 } 1069 }
886 return has_valid_range; 1070 return has_valid_range;
887 } 1071 }
888 1072
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 1073 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698