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

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 4 years, 11 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
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 HistogramBase* Build();
Alexei Svitkine (slow) 2016/01/14 16:43:13 Can this have a comment? Specifically also mention
bcwhite 2016/01/14 19:20:25 Done.
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_t 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_t flags_;
142
143 private:
144 DISALLOW_COPY_AND_ASSIGN(Factory);
145 };
146
147 HistogramBase* Histogram::Factory::Build() {
148 ImportPersistentHistograms();
Alexei Svitkine (slow) 2016/01/14 16:43:13 I don't understand this call. Is it needed? If so,
bcwhite 2016/01/14 19:20:25 Done.
149
150 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name_);
151 if (!histogram) {
Alexei Svitkine (slow) 2016/01/14 16:43:13 Prefer an early return if found, so the rest of th
bcwhite 2016/01/14 19:20:25 Found doesn't mean it's correct. There are additi
Alexei Svitkine (slow) 2016/01/14 21:53:41 Ok, that's fair. Let's keep as-is then.
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().
Alexei Svitkine (slow) 2016/01/14 16:43:13 Can this comment have more context? When exactly i
bcwhite 2016/01/14 19:20:25 Done.
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();
Alexei Svitkine (slow) 2016/01/14 16:43:13 Add a comment above this that mentions that curren
bcwhite 2016/01/14 19:20:25 Done.
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
Alexei Svitkine (slow) 2016/01/14 16:43:13 Nit: Remove empty line.
bcwhite 2016/01/14 19:20:25 Done.
216
87 HistogramBase* Histogram::FactoryGet(const std::string& name, 217 HistogramBase* Histogram::FactoryGet(const std::string& name,
88 Sample minimum, 218 Sample minimum,
89 Sample maximum, 219 Sample maximum,
90 size_t bucket_count, 220 size_t bucket_count,
91 int32_t flags) { 221 int32_t flags) {
92 bool valid_arguments = 222 bool valid_arguments =
93 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count); 223 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count);
94 DCHECK(valid_arguments); 224 DCHECK(valid_arguments);
95 225
96 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 226 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 } 227 }
125 228
126 HistogramBase* Histogram::FactoryTimeGet(const std::string& name, 229 HistogramBase* Histogram::FactoryTimeGet(const std::string& name,
127 TimeDelta minimum, 230 TimeDelta minimum,
128 TimeDelta maximum, 231 TimeDelta maximum,
129 size_t bucket_count, 232 size_t bucket_count,
130 int32_t flags) { 233 int32_t flags) {
131 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()), 234 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()),
132 static_cast<Sample>(maximum.InMilliseconds()), bucket_count, 235 static_cast<Sample>(maximum.InMilliseconds()), bucket_count,
133 flags); 236 flags);
134 } 237 }
135 238
136 HistogramBase* Histogram::FactoryGet(const char* name, 239 HistogramBase* Histogram::FactoryGet(const char* name,
137 Sample minimum, 240 Sample minimum,
138 Sample maximum, 241 Sample maximum,
139 size_t bucket_count, 242 size_t bucket_count,
140 int32_t flags) { 243 int32_t flags) {
141 return FactoryGet(std::string(name), minimum, maximum, bucket_count, flags); 244 return FactoryGet(std::string(name), minimum, maximum, bucket_count, flags);
142 } 245 }
143 246
144 HistogramBase* Histogram::FactoryTimeGet(const char* name, 247 HistogramBase* Histogram::FactoryTimeGet(const char* name,
145 TimeDelta minimum, 248 TimeDelta minimum,
146 TimeDelta maximum, 249 TimeDelta maximum,
147 size_t bucket_count, 250 size_t bucket_count,
148 int32_t flags) { 251 int32_t flags) {
149 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, 252 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count,
150 flags); 253 flags);
151 } 254 }
152 255
256 HistogramBase* Histogram::PersistentGet(const char* name,
257 Sample minimum,
258 Sample maximum,
259 const BucketRanges* ranges,
260 HistogramBase::AtomicCount* counts,
261 size_t counts_size,
262 HistogramSamples::Metadata* meta) {
263 return new Histogram(name, minimum, maximum, ranges, counts, counts_size,
264 meta);
265 }
266
153 // Calculate what range of values are held in each bucket. 267 // 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 268 // 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 269 // 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: 270 // (effectively making one bucket get no values). We need to avoid:
157 // ranges(i) == ranges(i + 1) 271 // ranges(i) == ranges(i + 1)
158 // To avoid that, we just do a fine-grained bucket width as far as we need to 272 // 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 273 // 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. 274 // that bucket onward we do use the exponential growth of buckets.
161 // 275 //
162 // static 276 // static
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 Sample maximum, 451 Sample maximum,
338 const BucketRanges* ranges) 452 const BucketRanges* ranges)
339 : HistogramBase(name), 453 : HistogramBase(name),
340 bucket_ranges_(ranges), 454 bucket_ranges_(ranges),
341 declared_min_(minimum), 455 declared_min_(minimum),
342 declared_max_(maximum) { 456 declared_max_(maximum) {
343 if (ranges) 457 if (ranges)
344 samples_.reset(new SampleVector(HashMetricName(name), ranges)); 458 samples_.reset(new SampleVector(HashMetricName(name), ranges));
345 } 459 }
346 460
461 Histogram::Histogram(const std::string& name,
462 Sample minimum,
463 Sample maximum,
464 const BucketRanges* ranges,
465 HistogramBase::AtomicCount* counts,
466 size_t counts_size,
467 HistogramSamples::Metadata* meta)
468 : HistogramBase(name),
469 bucket_ranges_(ranges),
470 declared_min_(minimum),
471 declared_max_(maximum) {
472 if (ranges) {
473 samples_.reset(new SampleVector(HashMetricName(name),
474 counts, counts_size, meta, ranges));
475 }
476 }
477
347 Histogram::~Histogram() { 478 Histogram::~Histogram() {
348 } 479 }
349 480
350 bool Histogram::PrintEmptyBucket(size_t index) const { 481 bool Histogram::PrintEmptyBucket(size_t index) const {
351 return true; 482 return true;
352 } 483 }
353 484
354 // Use the actual bucket widths (like a linear histogram) until the widths get 485 // 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 486 // 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 487 // 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; 669 ++index;
539 } 670 }
540 } 671 }
541 } 672 }
542 673
543 //------------------------------------------------------------------------------ 674 //------------------------------------------------------------------------------
544 // LinearHistogram: This histogram uses a traditional set of evenly spaced 675 // LinearHistogram: This histogram uses a traditional set of evenly spaced
545 // buckets. 676 // buckets.
546 //------------------------------------------------------------------------------ 677 //------------------------------------------------------------------------------
547 678
679 class LinearHistogram::Factory : public Histogram::Factory {
680 public:
681 Factory(const std::string& name,
682 HistogramBase::Sample minimum,
683 HistogramBase::Sample maximum,
684 size_t bucket_count,
685 int32_t flags,
686 const DescriptionPair* descriptions)
687 : Histogram::Factory(name, LINEAR_HISTOGRAM, minimum, maximum,
688 bucket_count, flags) {
689 descriptions_ = descriptions;
690 }
691
692 protected:
693 BucketRanges* CreateRanges() override {
694 BucketRanges* ranges = new BucketRanges(bucket_count_ + 1);
695 LinearHistogram::InitializeBucketRanges(minimum_, maximum_, ranges);
696 return ranges;
697 }
698
699 HistogramBase* HeapAlloc(const BucketRanges* ranges) override {
700 return new LinearHistogram(name_, minimum_, maximum_, ranges);
701 }
702
703 void FillHistogram(HistogramBase* base_histogram) override {
704 Histogram::Factory::FillHistogram(base_histogram);
705 LinearHistogram* histogram = static_cast<LinearHistogram*>(base_histogram);
706 // Set range descriptions.
707 if (descriptions_) {
708 for (int i = 0; descriptions_[i].description; ++i) {
709 histogram->bucket_description_[descriptions_[i].sample] =
710 descriptions_[i].description;
711 }
712 }
713 }
714
715 private:
716 const DescriptionPair* descriptions_;
717
718 DISALLOW_COPY_AND_ASSIGN(Factory);
719 };
720
548 LinearHistogram::~LinearHistogram() {} 721 LinearHistogram::~LinearHistogram() {}
549 722
550 HistogramBase* LinearHistogram::FactoryGet(const std::string& name, 723 HistogramBase* LinearHistogram::FactoryGet(const std::string& name,
551 Sample minimum, 724 Sample minimum,
552 Sample maximum, 725 Sample maximum,
553 size_t bucket_count, 726 size_t bucket_count,
554 int32_t flags) { 727 int32_t flags) {
555 return FactoryGetWithRangeDescription( 728 return FactoryGetWithRangeDescription(
556 name, minimum, maximum, bucket_count, flags, NULL); 729 name, minimum, maximum, bucket_count, flags, NULL);
557 } 730 }
(...skipping 18 matching lines...) Expand all
576 749
577 HistogramBase* LinearHistogram::FactoryTimeGet(const char* name, 750 HistogramBase* LinearHistogram::FactoryTimeGet(const char* name,
578 TimeDelta minimum, 751 TimeDelta minimum,
579 TimeDelta maximum, 752 TimeDelta maximum,
580 size_t bucket_count, 753 size_t bucket_count,
581 int32_t flags) { 754 int32_t flags) {
582 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, 755 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count,
583 flags); 756 flags);
584 } 757 }
585 758
759 HistogramBase* LinearHistogram::PersistentGet(
760 const char* name,
761 Sample minimum,
762 Sample maximum,
763 const BucketRanges* ranges,
764 HistogramBase::AtomicCount* counts,
765 size_t counts_size,
766 HistogramSamples::Metadata* meta) {
767 return new LinearHistogram(name, minimum, maximum, ranges, counts,
768 counts_size, meta);
769 }
770
586 HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( 771 HistogramBase* LinearHistogram::FactoryGetWithRangeDescription(
587 const std::string& name, 772 const std::string& name,
588 Sample minimum, 773 Sample minimum,
589 Sample maximum, 774 Sample maximum,
590 size_t bucket_count, 775 size_t bucket_count,
591 int32_t flags, 776 int32_t flags,
592 const DescriptionPair descriptions[]) { 777 const DescriptionPair descriptions[]) {
593 bool valid_arguments = Histogram::InspectConstructionArguments( 778 bool valid_arguments = Histogram::InspectConstructionArguments(
594 name, &minimum, &maximum, &bucket_count); 779 name, &minimum, &maximum, &bucket_count);
595 DCHECK(valid_arguments); 780 DCHECK(valid_arguments);
596 781
597 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 782 return Factory(name, minimum, maximum, bucket_count, flags, descriptions)
598 if (!histogram) { 783 .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 } 784 }
634 785
635 HistogramType LinearHistogram::GetHistogramType() const { 786 HistogramType LinearHistogram::GetHistogramType() const {
636 return LINEAR_HISTOGRAM; 787 return LINEAR_HISTOGRAM;
637 } 788 }
638 789
639 LinearHistogram::LinearHistogram(const std::string& name, 790 LinearHistogram::LinearHistogram(const std::string& name,
640 Sample minimum, 791 Sample minimum,
641 Sample maximum, 792 Sample maximum,
642 const BucketRanges* ranges) 793 const BucketRanges* ranges)
643 : Histogram(name, minimum, maximum, ranges) { 794 : Histogram(name, minimum, maximum, ranges) {
644 } 795 }
645 796
797 LinearHistogram::LinearHistogram(const std::string& name,
798 Sample minimum,
799 Sample maximum,
800 const BucketRanges* ranges,
801 HistogramBase::AtomicCount* counts,
802 size_t counts_size,
803 HistogramSamples::Metadata* meta)
804 : Histogram(name,
805 minimum,
806 maximum,
807 ranges,
808 counts,
809 counts_size,
810 meta) {}
811
646 double LinearHistogram::GetBucketSize(Count current, size_t i) const { 812 double LinearHistogram::GetBucketSize(Count current, size_t i) const {
647 DCHECK_GT(ranges(i + 1), ranges(i)); 813 DCHECK_GT(ranges(i + 1), ranges(i));
648 // Adjacent buckets with different widths would have "surprisingly" many (few) 814 // Adjacent buckets with different widths would have "surprisingly" many (few)
649 // samples in a histogram if we didn't normalize this way. 815 // samples in a histogram if we didn't normalize this way.
650 double denominator = ranges(i + 1) - ranges(i); 816 double denominator = ranges(i + 1) - ranges(i);
651 return current/denominator; 817 return current/denominator;
652 } 818 }
653 819
654 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const { 820 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const {
655 int range = ranges(i); 821 int range = ranges(i);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 // The serialized histogram might be corrupted. 865 // The serialized histogram might be corrupted.
700 return NULL; 866 return NULL;
701 } 867 }
702 return histogram; 868 return histogram;
703 } 869 }
704 870
705 //------------------------------------------------------------------------------ 871 //------------------------------------------------------------------------------
706 // This section provides implementation for BooleanHistogram. 872 // This section provides implementation for BooleanHistogram.
707 //------------------------------------------------------------------------------ 873 //------------------------------------------------------------------------------
708 874
875 class BooleanHistogram::Factory : public Histogram::Factory {
876 public:
877 Factory(const std::string& name, int32_t flags)
878 : Histogram::Factory(name, BOOLEAN_HISTOGRAM, 1, 2, 3, flags) {}
879
880 protected:
881 BucketRanges* CreateRanges() {
882 BucketRanges* ranges = new BucketRanges(3 + 1);
883 LinearHistogram::InitializeBucketRanges(1, 2, ranges);
884 return ranges;
885 }
886
887 HistogramBase* HeapAlloc(const BucketRanges* ranges) override {
888 return new BooleanHistogram(name_, ranges);
889 }
890
891 private:
892 DISALLOW_COPY_AND_ASSIGN(Factory);
893 };
894
709 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name, 895 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name,
710 int32_t flags) { 896 int32_t flags) {
711 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 897 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 } 898 }
730 899
731 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32_t flags) { 900 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32_t flags) {
732 return FactoryGet(std::string(name), flags); 901 return FactoryGet(std::string(name), flags);
733 } 902 }
734 903
904 HistogramBase* BooleanHistogram::PersistentGet(
905 const char* name,
906 const BucketRanges* ranges,
907 HistogramBase::AtomicCount* counts,
908 HistogramSamples::Metadata* meta) {
909 return new BooleanHistogram(name, ranges, counts, meta);
910 }
911
735 HistogramType BooleanHistogram::GetHistogramType() const { 912 HistogramType BooleanHistogram::GetHistogramType() const {
736 return BOOLEAN_HISTOGRAM; 913 return BOOLEAN_HISTOGRAM;
737 } 914 }
738 915
739 BooleanHistogram::BooleanHistogram(const std::string& name, 916 BooleanHistogram::BooleanHistogram(const std::string& name,
740 const BucketRanges* ranges) 917 const BucketRanges* ranges)
741 : LinearHistogram(name, 1, 2, ranges) {} 918 : LinearHistogram(name, 1, 2, ranges) {}
742 919
920 BooleanHistogram::BooleanHistogram(const std::string& name,
921 const BucketRanges* ranges,
922 HistogramBase::AtomicCount* counts,
923 HistogramSamples::Metadata* meta)
924 : LinearHistogram(name, 1, 2, ranges, counts, 2, meta) {}
925
743 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { 926 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) {
744 std::string histogram_name; 927 std::string histogram_name;
745 int flags; 928 int flags;
746 int declared_min; 929 int declared_min;
747 int declared_max; 930 int declared_max;
748 size_t bucket_count; 931 size_t bucket_count;
749 uint32_t range_checksum; 932 uint32_t range_checksum;
750 933
751 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, 934 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min,
752 &declared_max, &bucket_count, &range_checksum)) { 935 &declared_max, &bucket_count, &range_checksum)) {
753 return NULL; 936 return NULL;
754 } 937 }
755 938
756 HistogramBase* histogram = BooleanHistogram::FactoryGet( 939 HistogramBase* histogram = BooleanHistogram::FactoryGet(
757 histogram_name, flags); 940 histogram_name, flags);
758 if (!ValidateRangeChecksum(*histogram, range_checksum)) { 941 if (!ValidateRangeChecksum(*histogram, range_checksum)) {
759 // The serialized histogram might be corrupted. 942 // The serialized histogram might be corrupted.
760 return NULL; 943 return NULL;
761 } 944 }
762 return histogram; 945 return histogram;
763 } 946 }
764 947
765 //------------------------------------------------------------------------------ 948 //------------------------------------------------------------------------------
766 // CustomHistogram: 949 // CustomHistogram:
767 //------------------------------------------------------------------------------ 950 //------------------------------------------------------------------------------
768 951
952 class CustomHistogram::Factory : public Histogram::Factory {
953 public:
954 Factory(const std::string& name,
955 const std::vector<Sample>* custom_ranges,
956 int32_t flags)
957 : Histogram::Factory(name, CUSTOM_HISTOGRAM, 0, 0, 0, flags) {
958 custom_ranges_ = custom_ranges;
959 }
960
961 protected:
962 BucketRanges* CreateRanges() {
963 // Remove the duplicates in the custom ranges array.
964 std::vector<int> ranges = *custom_ranges_;
965 ranges.push_back(0); // Ensure we have a zero value.
966 ranges.push_back(HistogramBase::kSampleType_MAX);
967 std::sort(ranges.begin(), ranges.end());
968 ranges.erase(std::unique(ranges.begin(), ranges.end()), ranges.end());
969
970 BucketRanges* bucket_ranges = new BucketRanges(ranges.size());
971 for (size_t i = 0; i < ranges.size(); i++) {
972 bucket_ranges->set_range(i, ranges[i]);
973 }
974 bucket_ranges->ResetChecksum();
975 return bucket_ranges;
976 }
977
978 HistogramBase* HeapAlloc(const BucketRanges* ranges) override {
979 return new CustomHistogram(name_, ranges);
980 }
981
982 private:
983 const std::vector<Sample>* custom_ranges_;
984
985 DISALLOW_COPY_AND_ASSIGN(Factory);
986 };
987
769 HistogramBase* CustomHistogram::FactoryGet( 988 HistogramBase* CustomHistogram::FactoryGet(
770 const std::string& name, 989 const std::string& name,
771 const std::vector<Sample>& custom_ranges, 990 const std::vector<Sample>& custom_ranges,
772 int32_t flags) { 991 int32_t flags) {
773 CHECK(ValidateCustomRanges(custom_ranges)); 992 CHECK(ValidateCustomRanges(custom_ranges));
774 993
775 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 994 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 } 995 }
794 996
795 HistogramBase* CustomHistogram::FactoryGet( 997 HistogramBase* CustomHistogram::FactoryGet(
796 const char* name, 998 const char* name,
797 const std::vector<Sample>& custom_ranges, 999 const std::vector<Sample>& custom_ranges,
798 int32_t flags) { 1000 int32_t flags) {
799 return FactoryGet(std::string(name), custom_ranges, flags); 1001 return FactoryGet(std::string(name), custom_ranges, flags);
800 } 1002 }
801 1003
1004 HistogramBase* CustomHistogram::PersistentGet(
1005 const char* name,
1006 const BucketRanges* ranges,
1007 HistogramBase::AtomicCount* counts,
1008 size_t counts_size,
1009 HistogramSamples::Metadata* meta) {
1010 return new CustomHistogram(name, ranges, counts, counts_size, meta);
1011 }
1012
802 HistogramType CustomHistogram::GetHistogramType() const { 1013 HistogramType CustomHistogram::GetHistogramType() const {
803 return CUSTOM_HISTOGRAM; 1014 return CUSTOM_HISTOGRAM;
804 } 1015 }
805 1016
806 // static 1017 // static
807 std::vector<Sample> CustomHistogram::ArrayToCustomRanges( 1018 std::vector<Sample> CustomHistogram::ArrayToCustomRanges(
808 const Sample* values, size_t num_values) { 1019 const Sample* values, size_t num_values) {
809 std::vector<Sample> all_values; 1020 std::vector<Sample> all_values;
810 for (size_t i = 0; i < num_values; ++i) { 1021 for (size_t i = 0; i < num_values; ++i) {
811 Sample value = values[i]; 1022 Sample value = values[i];
812 all_values.push_back(value); 1023 all_values.push_back(value);
813 1024
814 // Ensure that a guard bucket is added. If we end up with duplicate 1025 // Ensure that a guard bucket is added. If we end up with duplicate
815 // values, FactoryGet will take care of removing them. 1026 // values, FactoryGet will take care of removing them.
816 all_values.push_back(value + 1); 1027 all_values.push_back(value + 1);
817 } 1028 }
818 return all_values; 1029 return all_values;
819 } 1030 }
820 1031
821 CustomHistogram::CustomHistogram(const std::string& name, 1032 CustomHistogram::CustomHistogram(const std::string& name,
822 const BucketRanges* ranges) 1033 const BucketRanges* ranges)
823 : Histogram(name, 1034 : Histogram(name,
824 ranges->range(1), 1035 ranges->range(1),
825 ranges->range(ranges->bucket_count() - 1), 1036 ranges->range(ranges->bucket_count() - 1),
826 ranges) {} 1037 ranges) {}
827 1038
1039 CustomHistogram::CustomHistogram(const std::string& name,
1040 const BucketRanges* ranges,
1041 HistogramBase::AtomicCount* counts,
1042 size_t counts_size,
1043 HistogramSamples::Metadata* meta)
1044 : Histogram(name,
1045 ranges->range(1),
1046 ranges->range(ranges->bucket_count() - 1),
1047 ranges,
1048 counts,
1049 counts_size,
1050 meta) {}
1051
828 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { 1052 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const {
829 if (!Histogram::SerializeInfoImpl(pickle)) 1053 if (!Histogram::SerializeInfoImpl(pickle))
830 return false; 1054 return false;
831 1055
832 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't 1056 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't
833 // write them. 1057 // write them.
834 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { 1058 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) {
835 if (!pickle->WriteInt(bucket_ranges()->range(i))) 1059 if (!pickle->WriteInt(bucket_ranges()->range(i)))
836 return false; 1060 return false;
837 } 1061 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
880 for (size_t i = 0; i < custom_ranges.size(); i++) { 1104 for (size_t i = 0; i < custom_ranges.size(); i++) {
881 Sample sample = custom_ranges[i]; 1105 Sample sample = custom_ranges[i];
882 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) 1106 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1)
883 return false; 1107 return false;
884 if (sample != 0) 1108 if (sample != 0)
885 has_valid_range = true; 1109 has_valid_range = true;
886 } 1110 }
887 return has_valid_range; 1111 return has_valid_range;
888 } 1112 }
889 1113
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 1114 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698