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

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: moved Create-Result histogram to private space and added to histograms.xml Created 4 years, 10 months 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
« no previous file with comments | « base/metrics/histogram.h ('k') | base/metrics/histogram_base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <limits.h> 12 #include <limits.h>
13 #include <math.h> 13 #include <math.h>
14 14
15 #include <algorithm> 15 #include <algorithm>
16 #include <string> 16 #include <string>
17 17
18 #include "base/compiler_specific.h" 18 #include "base/compiler_specific.h"
19 #include "base/debug/alias.h" 19 #include "base/debug/alias.h"
20 #include "base/logging.h" 20 #include "base/logging.h"
21 #include "base/metrics/histogram_macros.h" 21 #include "base/metrics/histogram_macros.h"
22 #include "base/metrics/histogram_persistence.h"
22 #include "base/metrics/metrics_hashes.h" 23 #include "base/metrics/metrics_hashes.h"
24 #include "base/metrics/persistent_memory_allocator.h"
23 #include "base/metrics/sample_vector.h" 25 #include "base/metrics/sample_vector.h"
24 #include "base/metrics/statistics_recorder.h" 26 #include "base/metrics/statistics_recorder.h"
25 #include "base/pickle.h" 27 #include "base/pickle.h"
26 #include "base/strings/string_util.h" 28 #include "base/strings/string_util.h"
27 #include "base/strings/stringprintf.h" 29 #include "base/strings/stringprintf.h"
28 #include "base/synchronization/lock.h" 30 #include "base/synchronization/lock.h"
29 #include "base/values.h" 31 #include "base/values.h"
30 32
31 namespace base { 33 namespace base {
32 34
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 } 79 }
78 80
79 } // namespace 81 } // namespace
80 82
81 typedef HistogramBase::Count Count; 83 typedef HistogramBase::Count Count;
82 typedef HistogramBase::Sample Sample; 84 typedef HistogramBase::Sample Sample;
83 85
84 // static 86 // static
85 const size_t Histogram::kBucketCount_MAX = 16384u; 87 const size_t Histogram::kBucketCount_MAX = 16384u;
86 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_t flags)
96 : Factory(name, HISTOGRAM, minimum, maximum, bucket_count, flags) {}
97
98 // Create histogram based on construction parameters. Caller takes
99 // ownership of the returned object.
100 HistogramBase* Build();
101
102 protected:
103 Factory(const std::string& name,
104 HistogramType histogram_type,
105 HistogramBase::Sample minimum,
106 HistogramBase::Sample maximum,
107 size_t bucket_count,
108 int32_t flags)
109 : name_(name),
110 histogram_type_(histogram_type),
111 minimum_(minimum),
112 maximum_(maximum),
113 bucket_count_(bucket_count),
114 flags_(flags) {}
115
116 // Create a BucketRanges structure appropriate for this histogram.
117 virtual BucketRanges* CreateRanges() {
118 BucketRanges* ranges = new BucketRanges(bucket_count_ + 1);
119 Histogram::InitializeBucketRanges(minimum_, maximum_, ranges);
120 return ranges;
121 }
122
123 // Allocate the correct Histogram object off the heap (in case persistent
124 // memory is not available).
125 virtual HistogramBase* HeapAlloc(const BucketRanges* ranges) {
126 return new Histogram(name_, minimum_, maximum_, ranges);
127 }
128
129 // Perform any required datafill on the just-created histogram. If
130 // overridden, be sure to call the "super" version.
131 virtual void FillHistogram(HistogramBase* histogram) {
132 histogram->SetFlags(flags_);
133 }
134
135 // These values are protected (instead of private) because they need to
136 // be accessible to methods of sub-classes in order to avoid passing
137 // unnecessary parameters everywhere.
138 const std::string& name_;
139 const HistogramType histogram_type_;
140 HistogramBase::Sample minimum_;
141 HistogramBase::Sample maximum_;
142 size_t bucket_count_;
143 int32_t flags_;
144
145 private:
146 DISALLOW_COPY_AND_ASSIGN(Factory);
147 };
148
149 HistogramBase* Histogram::Factory::Build() {
150 // Import histograms from known persistent storage. Histograms could have
151 // been added by other processes and they must be fetched and recognized
152 // locally in order to be found by FindHistograms() below. If the persistent
153 // memory segment is not shared between processes, this call does nothing.
154 ImportPersistentHistograms();
155
156 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name_);
157 if (!histogram) {
158 // To avoid racy destruction at shutdown, the following will be leaked.
159 const BucketRanges* created_ranges = CreateRanges();
160 const BucketRanges* registered_ranges =
161 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(created_ranges);
162
163 // In most cases, the bucket-count, minimum, and maximum values are known
164 // when the code is written and so are passed in explicitly. In other
165 // cases (such as with a CustomHistogram), they are calculated dynamically
166 // at run-time. In the latter case, those ctor parameters are zero and
167 // the results extracted from the result of CreateRanges().
168 if (bucket_count_ == 0) {
169 bucket_count_ = registered_ranges->bucket_count();
170 minimum_ = registered_ranges->range(1);
171 maximum_ = registered_ranges->range(bucket_count_ - 1);
172 }
173
174 // Try to create the histogram using a "persistent" allocator. As of
175 // 2015-01-14, the availability of such is controlled by a base::Feature
176 // that is off by default. If the allocator doesn't exist or if
177 // allocating from it fails, code below will allocate the histogram from
178 // the process heap.
179 PersistentMemoryAllocator::Reference histogram_ref = 0;
180 HistogramBase* tentative_histogram = nullptr;
181 PersistentMemoryAllocator* allocator =
182 GetPersistentHistogramMemoryAllocator();
183 if (allocator) {
184 flags_ |= HistogramBase::kIsPersistent;
185 tentative_histogram = AllocatePersistentHistogram(
186 allocator,
187 histogram_type_,
188 name_,
189 minimum_,
190 maximum_,
191 registered_ranges,
192 flags_,
193 &histogram_ref);
194 }
195
196 // Handle the case where no persistent allocator is present or the
197 // persistent allocation fails (perhaps because it is full).
198 if (!tentative_histogram) {
199 DCHECK(!histogram_ref); // Should never have been set.
200 DCHECK(!allocator); // Shouldn't have failed.
201 flags_ &= ~HistogramBase::kIsPersistent;
202 tentative_histogram = HeapAlloc(registered_ranges);
203 }
204
205 FillHistogram(tentative_histogram);
206 histogram =
207 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
208
209 // Persistent histograms need some follow-up processing.
210 if (histogram_ref) {
211 FinalizePersistentHistogram(histogram_ref,
212 histogram == tentative_histogram);
213 }
214 }
215
216 DCHECK_EQ(histogram_type_, histogram->GetHistogramType());
217 if (bucket_count_ != 0 &&
218 !histogram->HasConstructionArguments(minimum_, maximum_, bucket_count_)) {
219 // The construction arguments do not match the existing histogram. This can
220 // come about if an extension updates in the middle of a chrome run and has
221 // changed one of them, or simply by bad code within Chrome itself. We
222 // return NULL here with the expectation that bad code in Chrome will crash
223 // on dereference, but extension/Pepper APIs will guard against NULL and not
224 // crash.
225 DLOG(ERROR) << "Histogram " << name_ << " has bad construction arguments";
226 return nullptr;
227 }
228 return histogram;
229 }
230
87 HistogramBase* Histogram::FactoryGet(const std::string& name, 231 HistogramBase* Histogram::FactoryGet(const std::string& name,
88 Sample minimum, 232 Sample minimum,
89 Sample maximum, 233 Sample maximum,
90 size_t bucket_count, 234 size_t bucket_count,
91 int32_t flags) { 235 int32_t flags) {
92 bool valid_arguments = 236 bool valid_arguments =
93 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count); 237 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count);
94 DCHECK(valid_arguments); 238 DCHECK(valid_arguments);
95 239
96 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 240 return Factory(name, minimum, maximum, bucket_count, flags).Build();
97 if (!histogram) {
98 // To avoid racy destruction at shutdown, the following will be leaked.
99 BucketRanges* ranges = new BucketRanges(bucket_count + 1);
100 InitializeBucketRanges(minimum, maximum, ranges);
101 const BucketRanges* registered_ranges =
102 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
103
104 Histogram* tentative_histogram =
105 new Histogram(name, minimum, maximum, registered_ranges);
106
107 tentative_histogram->SetFlags(flags);
108 histogram =
109 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
110 }
111
112 DCHECK_EQ(HISTOGRAM, histogram->GetHistogramType());
113 if (!histogram->HasConstructionArguments(minimum, maximum, bucket_count)) {
114 // The construction arguments do not match the existing histogram. This can
115 // come about if an extension updates in the middle of a chrome run and has
116 // changed one of them, or simply by bad code within Chrome itself. We
117 // return NULL here with the expectation that bad code in Chrome will crash
118 // on dereference, but extension/Pepper APIs will guard against NULL and not
119 // crash.
120 DLOG(ERROR) << "Histogram " << name << " has bad construction arguments";
121 return NULL;
122 }
123 return histogram;
124 } 241 }
125 242
126 HistogramBase* Histogram::FactoryTimeGet(const std::string& name, 243 HistogramBase* Histogram::FactoryTimeGet(const std::string& name,
127 TimeDelta minimum, 244 TimeDelta minimum,
128 TimeDelta maximum, 245 TimeDelta maximum,
129 size_t bucket_count, 246 size_t bucket_count,
130 int32_t flags) { 247 int32_t flags) {
131 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()), 248 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()),
132 static_cast<Sample>(maximum.InMilliseconds()), bucket_count, 249 static_cast<Sample>(maximum.InMilliseconds()), bucket_count,
133 flags); 250 flags);
134 } 251 }
135 252
136 HistogramBase* Histogram::FactoryGet(const char* name, 253 HistogramBase* Histogram::FactoryGet(const char* name,
137 Sample minimum, 254 Sample minimum,
138 Sample maximum, 255 Sample maximum,
139 size_t bucket_count, 256 size_t bucket_count,
140 int32_t flags) { 257 int32_t flags) {
141 return FactoryGet(std::string(name), minimum, maximum, bucket_count, flags); 258 return FactoryGet(std::string(name), minimum, maximum, bucket_count, flags);
142 } 259 }
143 260
144 HistogramBase* Histogram::FactoryTimeGet(const char* name, 261 HistogramBase* Histogram::FactoryTimeGet(const char* name,
145 TimeDelta minimum, 262 TimeDelta minimum,
146 TimeDelta maximum, 263 TimeDelta maximum,
147 size_t bucket_count, 264 size_t bucket_count,
148 int32_t flags) { 265 int32_t flags) {
149 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, 266 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count,
150 flags); 267 flags);
151 } 268 }
152 269
270 HistogramBase* Histogram::PersistentGet(const std::string& name,
271 Sample minimum,
272 Sample maximum,
273 const BucketRanges* ranges,
274 HistogramBase::AtomicCount* counts,
275 size_t counts_size,
276 HistogramSamples::Metadata* meta) {
277 return new Histogram(name, minimum, maximum, ranges, counts, counts_size,
278 meta);
279 }
280
153 // Calculate what range of values are held in each bucket. 281 // Calculate what range of values are held in each bucket.
154 // We have to be careful that we don't pick a ratio between starting points in 282 // We have to be careful that we don't pick a ratio between starting points in
155 // consecutive buckets that is sooo small, that the integer bounds are the same 283 // consecutive buckets that is sooo small, that the integer bounds are the same
156 // (effectively making one bucket get no values). We need to avoid: 284 // (effectively making one bucket get no values). We need to avoid:
157 // ranges(i) == ranges(i + 1) 285 // ranges(i) == ranges(i + 1)
158 // To avoid that, we just do a fine-grained bucket width as far as we need to 286 // To avoid that, we just do a fine-grained bucket width as far as we need to
159 // until we get a ratio that moves us along at least 2 units at a time. From 287 // until we get a ratio that moves us along at least 2 units at a time. From
160 // that bucket onward we do use the exponential growth of buckets. 288 // that bucket onward we do use the exponential growth of buckets.
161 // 289 //
162 // static 290 // static
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 Sample maximum, 465 Sample maximum,
338 const BucketRanges* ranges) 466 const BucketRanges* ranges)
339 : HistogramBase(name), 467 : HistogramBase(name),
340 bucket_ranges_(ranges), 468 bucket_ranges_(ranges),
341 declared_min_(minimum), 469 declared_min_(minimum),
342 declared_max_(maximum) { 470 declared_max_(maximum) {
343 if (ranges) 471 if (ranges)
344 samples_.reset(new SampleVector(HashMetricName(name), ranges)); 472 samples_.reset(new SampleVector(HashMetricName(name), ranges));
345 } 473 }
346 474
475 Histogram::Histogram(const std::string& name,
476 Sample minimum,
477 Sample maximum,
478 const BucketRanges* ranges,
479 HistogramBase::AtomicCount* counts,
480 size_t counts_size,
481 HistogramSamples::Metadata* meta)
482 : HistogramBase(name),
483 bucket_ranges_(ranges),
484 declared_min_(minimum),
485 declared_max_(maximum) {
486 if (ranges) {
487 samples_.reset(new SampleVector(HashMetricName(name),
488 counts, counts_size, meta, ranges));
489 }
490 }
491
347 Histogram::~Histogram() { 492 Histogram::~Histogram() {
348 } 493 }
349 494
350 bool Histogram::PrintEmptyBucket(size_t index) const { 495 bool Histogram::PrintEmptyBucket(size_t index) const {
351 return true; 496 return true;
352 } 497 }
353 498
354 // Use the actual bucket widths (like a linear histogram) until the widths get 499 // Use the actual bucket widths (like a linear histogram) until the widths get
355 // over some transition value, and then use that transition width. Exponentials 500 // over some transition value, and then use that transition width. Exponentials
356 // get so big so fast (and we don't expect to see a lot of entries in the large 501 // 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
538 ++index; 683 ++index;
539 } 684 }
540 } 685 }
541 } 686 }
542 687
543 //------------------------------------------------------------------------------ 688 //------------------------------------------------------------------------------
544 // LinearHistogram: This histogram uses a traditional set of evenly spaced 689 // LinearHistogram: This histogram uses a traditional set of evenly spaced
545 // buckets. 690 // buckets.
546 //------------------------------------------------------------------------------ 691 //------------------------------------------------------------------------------
547 692
693 class LinearHistogram::Factory : public Histogram::Factory {
694 public:
695 Factory(const std::string& name,
696 HistogramBase::Sample minimum,
697 HistogramBase::Sample maximum,
698 size_t bucket_count,
699 int32_t flags,
700 const DescriptionPair* descriptions)
701 : Histogram::Factory(name, LINEAR_HISTOGRAM, minimum, maximum,
702 bucket_count, flags) {
703 descriptions_ = descriptions;
704 }
705
706 protected:
707 BucketRanges* CreateRanges() override {
708 BucketRanges* ranges = new BucketRanges(bucket_count_ + 1);
709 LinearHistogram::InitializeBucketRanges(minimum_, maximum_, ranges);
710 return ranges;
711 }
712
713 HistogramBase* HeapAlloc(const BucketRanges* ranges) override {
714 return new LinearHistogram(name_, minimum_, maximum_, ranges);
715 }
716
717 void FillHistogram(HistogramBase* base_histogram) override {
718 Histogram::Factory::FillHistogram(base_histogram);
719 LinearHistogram* histogram = static_cast<LinearHistogram*>(base_histogram);
720 // Set range descriptions.
721 if (descriptions_) {
722 for (int i = 0; descriptions_[i].description; ++i) {
723 histogram->bucket_description_[descriptions_[i].sample] =
724 descriptions_[i].description;
725 }
726 }
727 }
728
729 private:
730 const DescriptionPair* descriptions_;
731
732 DISALLOW_COPY_AND_ASSIGN(Factory);
733 };
734
548 LinearHistogram::~LinearHistogram() {} 735 LinearHistogram::~LinearHistogram() {}
549 736
550 HistogramBase* LinearHistogram::FactoryGet(const std::string& name, 737 HistogramBase* LinearHistogram::FactoryGet(const std::string& name,
551 Sample minimum, 738 Sample minimum,
552 Sample maximum, 739 Sample maximum,
553 size_t bucket_count, 740 size_t bucket_count,
554 int32_t flags) { 741 int32_t flags) {
555 return FactoryGetWithRangeDescription( 742 return FactoryGetWithRangeDescription(
556 name, minimum, maximum, bucket_count, flags, NULL); 743 name, minimum, maximum, bucket_count, flags, NULL);
557 } 744 }
(...skipping 18 matching lines...) Expand all
576 763
577 HistogramBase* LinearHistogram::FactoryTimeGet(const char* name, 764 HistogramBase* LinearHistogram::FactoryTimeGet(const char* name,
578 TimeDelta minimum, 765 TimeDelta minimum,
579 TimeDelta maximum, 766 TimeDelta maximum,
580 size_t bucket_count, 767 size_t bucket_count,
581 int32_t flags) { 768 int32_t flags) {
582 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, 769 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count,
583 flags); 770 flags);
584 } 771 }
585 772
773 HistogramBase* LinearHistogram::PersistentGet(
774 const std::string& name,
775 Sample minimum,
776 Sample maximum,
777 const BucketRanges* ranges,
778 HistogramBase::AtomicCount* counts,
779 size_t counts_size,
780 HistogramSamples::Metadata* meta) {
781 return new LinearHistogram(name, minimum, maximum, ranges, counts,
782 counts_size, meta);
783 }
784
586 HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( 785 HistogramBase* LinearHistogram::FactoryGetWithRangeDescription(
587 const std::string& name, 786 const std::string& name,
588 Sample minimum, 787 Sample minimum,
589 Sample maximum, 788 Sample maximum,
590 size_t bucket_count, 789 size_t bucket_count,
591 int32_t flags, 790 int32_t flags,
592 const DescriptionPair descriptions[]) { 791 const DescriptionPair descriptions[]) {
593 bool valid_arguments = Histogram::InspectConstructionArguments( 792 bool valid_arguments = Histogram::InspectConstructionArguments(
594 name, &minimum, &maximum, &bucket_count); 793 name, &minimum, &maximum, &bucket_count);
595 DCHECK(valid_arguments); 794 DCHECK(valid_arguments);
596 795
597 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 796 return Factory(name, minimum, maximum, bucket_count, flags, descriptions)
598 if (!histogram) { 797 .Build();
599 // To avoid racy destruction at shutdown, the following will be leaked.
600 BucketRanges* ranges = new BucketRanges(bucket_count + 1);
601 InitializeBucketRanges(minimum, maximum, ranges);
602 const BucketRanges* registered_ranges =
603 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
604
605 LinearHistogram* tentative_histogram =
606 new LinearHistogram(name, minimum, maximum, registered_ranges);
607
608 // Set range descriptions.
609 if (descriptions) {
610 for (int i = 0; descriptions[i].description; ++i) {
611 tentative_histogram->bucket_description_[descriptions[i].sample] =
612 descriptions[i].description;
613 }
614 }
615
616 tentative_histogram->SetFlags(flags);
617 histogram =
618 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
619 }
620
621 DCHECK_EQ(LINEAR_HISTOGRAM, histogram->GetHistogramType());
622 if (!histogram->HasConstructionArguments(minimum, maximum, bucket_count)) {
623 // The construction arguments do not match the existing histogram. This can
624 // come about if an extension updates in the middle of a chrome run and has
625 // changed one of them, or simply by bad code within Chrome itself. We
626 // return NULL here with the expectation that bad code in Chrome will crash
627 // on dereference, but extension/Pepper APIs will guard against NULL and not
628 // crash.
629 DLOG(ERROR) << "Histogram " << name << " has bad construction arguments";
630 return NULL;
631 }
632 return histogram;
633 } 798 }
634 799
635 HistogramType LinearHistogram::GetHistogramType() const { 800 HistogramType LinearHistogram::GetHistogramType() const {
636 return LINEAR_HISTOGRAM; 801 return LINEAR_HISTOGRAM;
637 } 802 }
638 803
639 LinearHistogram::LinearHistogram(const std::string& name, 804 LinearHistogram::LinearHistogram(const std::string& name,
640 Sample minimum, 805 Sample minimum,
641 Sample maximum, 806 Sample maximum,
642 const BucketRanges* ranges) 807 const BucketRanges* ranges)
643 : Histogram(name, minimum, maximum, ranges) { 808 : Histogram(name, minimum, maximum, ranges) {
644 } 809 }
645 810
811 LinearHistogram::LinearHistogram(const std::string& name,
812 Sample minimum,
813 Sample maximum,
814 const BucketRanges* ranges,
815 HistogramBase::AtomicCount* counts,
816 size_t counts_size,
817 HistogramSamples::Metadata* meta)
818 : Histogram(name,
819 minimum,
820 maximum,
821 ranges,
822 counts,
823 counts_size,
824 meta) {}
825
646 double LinearHistogram::GetBucketSize(Count current, size_t i) const { 826 double LinearHistogram::GetBucketSize(Count current, size_t i) const {
647 DCHECK_GT(ranges(i + 1), ranges(i)); 827 DCHECK_GT(ranges(i + 1), ranges(i));
648 // Adjacent buckets with different widths would have "surprisingly" many (few) 828 // Adjacent buckets with different widths would have "surprisingly" many (few)
649 // samples in a histogram if we didn't normalize this way. 829 // samples in a histogram if we didn't normalize this way.
650 double denominator = ranges(i + 1) - ranges(i); 830 double denominator = ranges(i + 1) - ranges(i);
651 return current/denominator; 831 return current/denominator;
652 } 832 }
653 833
654 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const { 834 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const {
655 int range = ranges(i); 835 int range = ranges(i);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 // The serialized histogram might be corrupted. 879 // The serialized histogram might be corrupted.
700 return NULL; 880 return NULL;
701 } 881 }
702 return histogram; 882 return histogram;
703 } 883 }
704 884
705 //------------------------------------------------------------------------------ 885 //------------------------------------------------------------------------------
706 // This section provides implementation for BooleanHistogram. 886 // This section provides implementation for BooleanHistogram.
707 //------------------------------------------------------------------------------ 887 //------------------------------------------------------------------------------
708 888
889 class BooleanHistogram::Factory : public Histogram::Factory {
890 public:
891 Factory(const std::string& name, int32_t flags)
892 : Histogram::Factory(name, BOOLEAN_HISTOGRAM, 1, 2, 3, flags) {}
893
894 protected:
895 BucketRanges* CreateRanges() override {
896 BucketRanges* ranges = new BucketRanges(3 + 1);
897 LinearHistogram::InitializeBucketRanges(1, 2, ranges);
898 return ranges;
899 }
900
901 HistogramBase* HeapAlloc(const BucketRanges* ranges) override {
902 return new BooleanHistogram(name_, ranges);
903 }
904
905 private:
906 DISALLOW_COPY_AND_ASSIGN(Factory);
907 };
908
709 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name, 909 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name,
710 int32_t flags) { 910 int32_t flags) {
711 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 911 return Factory(name, flags).Build();
712 if (!histogram) {
713 // To avoid racy destruction at shutdown, the following will be leaked.
714 BucketRanges* ranges = new BucketRanges(4);
715 LinearHistogram::InitializeBucketRanges(1, 2, ranges);
716 const BucketRanges* registered_ranges =
717 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
718
719 BooleanHistogram* tentative_histogram =
720 new BooleanHistogram(name, registered_ranges);
721
722 tentative_histogram->SetFlags(flags);
723 histogram =
724 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
725 }
726
727 DCHECK_EQ(BOOLEAN_HISTOGRAM, histogram->GetHistogramType());
728 return histogram;
729 } 912 }
730 913
731 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32_t flags) { 914 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32_t flags) {
732 return FactoryGet(std::string(name), flags); 915 return FactoryGet(std::string(name), flags);
733 } 916 }
734 917
918 HistogramBase* BooleanHistogram::PersistentGet(
919 const std::string& name,
920 const BucketRanges* ranges,
921 HistogramBase::AtomicCount* counts,
922 HistogramSamples::Metadata* meta) {
923 return new BooleanHistogram(name, ranges, counts, meta);
924 }
925
735 HistogramType BooleanHistogram::GetHistogramType() const { 926 HistogramType BooleanHistogram::GetHistogramType() const {
736 return BOOLEAN_HISTOGRAM; 927 return BOOLEAN_HISTOGRAM;
737 } 928 }
738 929
739 BooleanHistogram::BooleanHistogram(const std::string& name, 930 BooleanHistogram::BooleanHistogram(const std::string& name,
740 const BucketRanges* ranges) 931 const BucketRanges* ranges)
741 : LinearHistogram(name, 1, 2, ranges) {} 932 : LinearHistogram(name, 1, 2, ranges) {}
742 933
934 BooleanHistogram::BooleanHistogram(const std::string& name,
935 const BucketRanges* ranges,
936 HistogramBase::AtomicCount* counts,
937 HistogramSamples::Metadata* meta)
938 : LinearHistogram(name, 1, 2, ranges, counts, 2, meta) {}
939
743 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { 940 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) {
744 std::string histogram_name; 941 std::string histogram_name;
745 int flags; 942 int flags;
746 int declared_min; 943 int declared_min;
747 int declared_max; 944 int declared_max;
748 size_t bucket_count; 945 size_t bucket_count;
749 uint32_t range_checksum; 946 uint32_t range_checksum;
750 947
751 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, 948 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min,
752 &declared_max, &bucket_count, &range_checksum)) { 949 &declared_max, &bucket_count, &range_checksum)) {
753 return NULL; 950 return NULL;
754 } 951 }
755 952
756 HistogramBase* histogram = BooleanHistogram::FactoryGet( 953 HistogramBase* histogram = BooleanHistogram::FactoryGet(
757 histogram_name, flags); 954 histogram_name, flags);
758 if (!ValidateRangeChecksum(*histogram, range_checksum)) { 955 if (!ValidateRangeChecksum(*histogram, range_checksum)) {
759 // The serialized histogram might be corrupted. 956 // The serialized histogram might be corrupted.
760 return NULL; 957 return NULL;
761 } 958 }
762 return histogram; 959 return histogram;
763 } 960 }
764 961
765 //------------------------------------------------------------------------------ 962 //------------------------------------------------------------------------------
766 // CustomHistogram: 963 // CustomHistogram:
767 //------------------------------------------------------------------------------ 964 //------------------------------------------------------------------------------
768 965
966 class CustomHistogram::Factory : public Histogram::Factory {
967 public:
968 Factory(const std::string& name,
969 const std::vector<Sample>* custom_ranges,
970 int32_t flags)
971 : Histogram::Factory(name, CUSTOM_HISTOGRAM, 0, 0, 0, flags) {
972 custom_ranges_ = custom_ranges;
973 }
974
975 protected:
976 BucketRanges* CreateRanges() override {
977 // Remove the duplicates in the custom ranges array.
978 std::vector<int> ranges = *custom_ranges_;
979 ranges.push_back(0); // Ensure we have a zero value.
980 ranges.push_back(HistogramBase::kSampleType_MAX);
981 std::sort(ranges.begin(), ranges.end());
982 ranges.erase(std::unique(ranges.begin(), ranges.end()), ranges.end());
983
984 BucketRanges* bucket_ranges = new BucketRanges(ranges.size());
985 for (size_t i = 0; i < ranges.size(); i++) {
986 bucket_ranges->set_range(i, ranges[i]);
987 }
988 bucket_ranges->ResetChecksum();
989 return bucket_ranges;
990 }
991
992 HistogramBase* HeapAlloc(const BucketRanges* ranges) override {
993 return new CustomHistogram(name_, ranges);
994 }
995
996 private:
997 const std::vector<Sample>* custom_ranges_;
998
999 DISALLOW_COPY_AND_ASSIGN(Factory);
1000 };
1001
769 HistogramBase* CustomHistogram::FactoryGet( 1002 HistogramBase* CustomHistogram::FactoryGet(
770 const std::string& name, 1003 const std::string& name,
771 const std::vector<Sample>& custom_ranges, 1004 const std::vector<Sample>& custom_ranges,
772 int32_t flags) { 1005 int32_t flags) {
773 CHECK(ValidateCustomRanges(custom_ranges)); 1006 CHECK(ValidateCustomRanges(custom_ranges));
774 1007
775 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 1008 return Factory(name, &custom_ranges, flags).Build();
776 if (!histogram) {
777 BucketRanges* ranges = CreateBucketRangesFromCustomRanges(custom_ranges);
778 const BucketRanges* registered_ranges =
779 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
780
781 // To avoid racy destruction at shutdown, the following will be leaked.
782 CustomHistogram* tentative_histogram =
783 new CustomHistogram(name, registered_ranges);
784
785 tentative_histogram->SetFlags(flags);
786
787 histogram =
788 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
789 }
790
791 DCHECK_EQ(histogram->GetHistogramType(), CUSTOM_HISTOGRAM);
792 return histogram;
793 } 1009 }
794 1010
795 HistogramBase* CustomHistogram::FactoryGet( 1011 HistogramBase* CustomHistogram::FactoryGet(
796 const char* name, 1012 const char* name,
797 const std::vector<Sample>& custom_ranges, 1013 const std::vector<Sample>& custom_ranges,
798 int32_t flags) { 1014 int32_t flags) {
799 return FactoryGet(std::string(name), custom_ranges, flags); 1015 return FactoryGet(std::string(name), custom_ranges, flags);
800 } 1016 }
801 1017
1018 HistogramBase* CustomHistogram::PersistentGet(
1019 const std::string& name,
1020 const BucketRanges* ranges,
1021 HistogramBase::AtomicCount* counts,
1022 size_t counts_size,
1023 HistogramSamples::Metadata* meta) {
1024 return new CustomHistogram(name, ranges, counts, counts_size, meta);
1025 }
1026
802 HistogramType CustomHistogram::GetHistogramType() const { 1027 HistogramType CustomHistogram::GetHistogramType() const {
803 return CUSTOM_HISTOGRAM; 1028 return CUSTOM_HISTOGRAM;
804 } 1029 }
805 1030
806 // static 1031 // static
807 std::vector<Sample> CustomHistogram::ArrayToCustomRanges( 1032 std::vector<Sample> CustomHistogram::ArrayToCustomRanges(
808 const Sample* values, size_t num_values) { 1033 const Sample* values, size_t num_values) {
809 std::vector<Sample> all_values; 1034 std::vector<Sample> all_values;
810 for (size_t i = 0; i < num_values; ++i) { 1035 for (size_t i = 0; i < num_values; ++i) {
811 Sample value = values[i]; 1036 Sample value = values[i];
812 all_values.push_back(value); 1037 all_values.push_back(value);
813 1038
814 // Ensure that a guard bucket is added. If we end up with duplicate 1039 // Ensure that a guard bucket is added. If we end up with duplicate
815 // values, FactoryGet will take care of removing them. 1040 // values, FactoryGet will take care of removing them.
816 all_values.push_back(value + 1); 1041 all_values.push_back(value + 1);
817 } 1042 }
818 return all_values; 1043 return all_values;
819 } 1044 }
820 1045
821 CustomHistogram::CustomHistogram(const std::string& name, 1046 CustomHistogram::CustomHistogram(const std::string& name,
822 const BucketRanges* ranges) 1047 const BucketRanges* ranges)
823 : Histogram(name, 1048 : Histogram(name,
824 ranges->range(1), 1049 ranges->range(1),
825 ranges->range(ranges->bucket_count() - 1), 1050 ranges->range(ranges->bucket_count() - 1),
826 ranges) {} 1051 ranges) {}
827 1052
1053 CustomHistogram::CustomHistogram(const std::string& name,
1054 const BucketRanges* ranges,
1055 HistogramBase::AtomicCount* counts,
1056 size_t counts_size,
1057 HistogramSamples::Metadata* meta)
1058 : Histogram(name,
1059 ranges->range(1),
1060 ranges->range(ranges->bucket_count() - 1),
1061 ranges,
1062 counts,
1063 counts_size,
1064 meta) {}
1065
828 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { 1066 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const {
829 if (!Histogram::SerializeInfoImpl(pickle)) 1067 if (!Histogram::SerializeInfoImpl(pickle))
830 return false; 1068 return false;
831 1069
832 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't 1070 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't
833 // write them. 1071 // write them.
834 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { 1072 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) {
835 if (!pickle->WriteInt(bucket_ranges()->range(i))) 1073 if (!pickle->WriteInt(bucket_ranges()->range(i)))
836 return false; 1074 return false;
837 } 1075 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
880 for (size_t i = 0; i < custom_ranges.size(); i++) { 1118 for (size_t i = 0; i < custom_ranges.size(); i++) {
881 Sample sample = custom_ranges[i]; 1119 Sample sample = custom_ranges[i];
882 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) 1120 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1)
883 return false; 1121 return false;
884 if (sample != 0) 1122 if (sample != 0)
885 has_valid_range = true; 1123 has_valid_range = true;
886 } 1124 }
887 return has_valid_range; 1125 return has_valid_range;
888 } 1126 }
889 1127
890 // static
891 BucketRanges* CustomHistogram::CreateBucketRangesFromCustomRanges(
892 const std::vector<Sample>& custom_ranges) {
893 // Remove the duplicates in the custom ranges array.
894 std::vector<int> ranges = custom_ranges;
895 ranges.push_back(0); // Ensure we have a zero value.
896 ranges.push_back(HistogramBase::kSampleType_MAX);
897 std::sort(ranges.begin(), ranges.end());
898 ranges.erase(std::unique(ranges.begin(), ranges.end()), ranges.end());
899
900 BucketRanges* bucket_ranges = new BucketRanges(ranges.size());
901 for (size_t i = 0; i < ranges.size(); i++) {
902 bucket_ranges->set_range(i, ranges[i]);
903 }
904 bucket_ranges->ResetChecksum();
905 return bucket_ranges;
906 }
907
908 } // namespace base 1128 } // namespace base
OLDNEW
« no previous file with comments | « base/metrics/histogram.h ('k') | base/metrics/histogram_base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698