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

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: reorganized persistence around PersistentGet methods to fix visibility problems 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
Alexei Svitkine (slow) 2016/01/12 21:54:44 Nit: Remove the extra line.
bcwhite 2016/01/13 13:38:29 Done.
90 class Histogram::Factory {
91 public:
92 Factory(const std::string& name,
93 HistogramBase::Sample minimum,
94 HistogramBase::Sample maximum,
95 size_t bucket_count,
96 int32_t flags)
97 : Factory(name, HISTOGRAM, minimum, maximum, bucket_count, flags) {}
98
99 HistogramBase* Build();
100
101 protected:
102 Factory(const std::string& name,
103 HistogramType histogram_type,
104 HistogramBase::Sample minimum,
105 HistogramBase::Sample maximum,
106 size_t bucket_count,
107 int32_t flags)
108 : name_(name),
109 histogram_type_(histogram_type),
110 minimum_(minimum),
111 maximum_(maximum),
112 bucket_count_(bucket_count),
113 flags_(flags) {}
114
115 // Create a BucketRanges structure appropriate for this histogram.
116 virtual BucketRanges* CreateRanges() {
117 BucketRanges* ranges = new BucketRanges(bucket_count_ + 1);
118 Histogram::InitializeBucketRanges(minimum_, maximum_, ranges);
119 return ranges;
120 }
121
122 // Allocate the correct Histogram object off the heap (in case persistent
123 // memory is not available).
124 virtual HistogramBase* HeapAlloc(const BucketRanges* ranges) {
125 return new Histogram(name_, minimum_, maximum_, ranges);
126 }
127
128 // Perform any required datafill on the just-created histogram. If
129 // overridden, be sure to call the "super" version.
130 virtual void FillHistogram(HistogramBase* histogram) {
131 histogram->SetFlags(flags_);
132 }
133
134 // These values are protected (instead of private) because they need to
135 // be accessible to methods of sub-classes in order to avoid passing
136 // unnecessary parameters everywhere.
137 const std::string& name_;
138 const HistogramType histogram_type_;
139 HistogramBase::Sample minimum_;
140 HistogramBase::Sample maximum_;
141 size_t bucket_count_;
142 int32_t flags_;
143
144 private:
145 DISALLOW_COPY_AND_ASSIGN(Factory);
146 };
147
148 HistogramBase* Histogram::Factory::Build() {
149 ImportPersistentHistograms();
150
151 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name_);
152 if (!histogram) {
153 // To avoid racy destruction at shutdown, the following will be leaked.
154 const BucketRanges* created_ranges = CreateRanges();
155 const BucketRanges* registered_ranges =
156 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(created_ranges);
157
158 // Sometimes the bucket info is dynamically determined in CreateRanges().
159 if (bucket_count_ == 0) {
160 bucket_count_ = registered_ranges->bucket_count();
161 minimum_ = registered_ranges->range(1);
162 maximum_ = registered_ranges->range(bucket_count_ - 1);
163 }
164
165 PersistentMemoryAllocator::Reference histogram_ref = 0;
166 HistogramBase* tentative_histogram = nullptr;
167 PersistentMemoryAllocator* allocator =
168 GetPersistentHistogramMemoryAllocator();
169 if (allocator) {
170 flags_ |= HistogramBase::kIsPersistent;
171 tentative_histogram = AllocatePersistentHistogram(
172 allocator,
173 histogram_type_,
174 name_,
175 minimum_,
176 maximum_,
177 registered_ranges,
178 flags_,
179 &histogram_ref);
180 }
181
182 // Handle the case where no persistent allocator is present or the
183 // persistent allocation fails (perhaps because it is full).
184 if (!tentative_histogram) {
185 DCHECK(!histogram_ref); // Should never have been set.
186 DCHECK(!allocator); // Shouldn't have failed.
187 flags_ &= ~HistogramBase::kIsPersistent;
188 tentative_histogram = HeapAlloc(registered_ranges);
189 }
190
191 FillHistogram(tentative_histogram);
192 histogram =
193 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
194
195 // Persistent histograms need some follow-up processing.
196 if (histogram_ref) {
197 FinalizePersistentHistogram(histogram_ref,
198 histogram == tentative_histogram);
199 }
200 }
201
202 DCHECK_EQ(histogram_type_, histogram->GetHistogramType());
203 if (bucket_count_ != 0 &&
204 !histogram->HasConstructionArguments(minimum_, maximum_, bucket_count_)) {
205 // The construction arguments do not match the existing histogram. This can
206 // come about if an extension updates in the middle of a chrome run and has
207 // changed one of them, or simply by bad code within Chrome itself. We
208 // return NULL here with the expectation that bad code in Chrome will crash
209 // on dereference, but extension/Pepper APIs will guard against NULL and not
210 // crash.
211 DLOG(ERROR) << "Histogram " << name_ << " has bad construction arguments";
212 return nullptr;
213 }
214 return histogram;
215 }
216
217
87 HistogramBase* Histogram::FactoryGet(const std::string& name, 218 HistogramBase* Histogram::FactoryGet(const std::string& name,
88 Sample minimum, 219 Sample minimum,
89 Sample maximum, 220 Sample maximum,
90 size_t bucket_count, 221 size_t bucket_count,
91 int32_t flags) { 222 int32_t flags) {
92 bool valid_arguments = 223 bool valid_arguments =
93 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count); 224 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count);
94 DCHECK(valid_arguments); 225 DCHECK(valid_arguments);
95 226
96 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 227 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 } 228 }
125 229
126 HistogramBase* Histogram::FactoryTimeGet(const std::string& name, 230 HistogramBase* Histogram::FactoryTimeGet(const std::string& name,
127 TimeDelta minimum, 231 TimeDelta minimum,
128 TimeDelta maximum, 232 TimeDelta maximum,
129 size_t bucket_count, 233 size_t bucket_count,
130 int32_t flags) { 234 int32_t flags) {
131 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()), 235 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()),
132 static_cast<Sample>(maximum.InMilliseconds()), bucket_count, 236 static_cast<Sample>(maximum.InMilliseconds()), bucket_count,
133 flags); 237 flags);
134 } 238 }
135 239
136 HistogramBase* Histogram::FactoryGet(const char* name, 240 HistogramBase* Histogram::FactoryGet(const char* name,
137 Sample minimum, 241 Sample minimum,
138 Sample maximum, 242 Sample maximum,
139 size_t bucket_count, 243 size_t bucket_count,
140 int32_t flags) { 244 int32_t flags) {
141 return FactoryGet(std::string(name), minimum, maximum, bucket_count, flags); 245 return FactoryGet(std::string(name), minimum, maximum, bucket_count, flags);
142 } 246 }
143 247
144 HistogramBase* Histogram::FactoryTimeGet(const char* name, 248 HistogramBase* Histogram::FactoryTimeGet(const char* name,
145 TimeDelta minimum, 249 TimeDelta minimum,
146 TimeDelta maximum, 250 TimeDelta maximum,
147 size_t bucket_count, 251 size_t bucket_count,
148 int32_t flags) { 252 int32_t flags) {
149 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, 253 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count,
150 flags); 254 flags);
151 } 255 }
152 256
257 HistogramBase* Histogram::PersistentGet(const char* name,
258 Sample minimum,
259 Sample maximum,
260 const BucketRanges* ranges,
261 HistogramBase::AtomicCount* counts,
262 size_t counts_size,
263 HistogramSamples::Metadata* meta) {
264 return new Histogram(name, minimum, maximum, ranges, counts, counts_size,
265 meta);
266 }
267
153 // Calculate what range of values are held in each bucket. 268 // 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 269 // 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 270 // 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: 271 // (effectively making one bucket get no values). We need to avoid:
157 // ranges(i) == ranges(i + 1) 272 // ranges(i) == ranges(i + 1)
158 // To avoid that, we just do a fine-grained bucket width as far as we need to 273 // 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 274 // 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. 275 // that bucket onward we do use the exponential growth of buckets.
161 // 276 //
162 // static 277 // static
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 Sample maximum, 452 Sample maximum,
338 const BucketRanges* ranges) 453 const BucketRanges* ranges)
339 : HistogramBase(name), 454 : HistogramBase(name),
340 bucket_ranges_(ranges), 455 bucket_ranges_(ranges),
341 declared_min_(minimum), 456 declared_min_(minimum),
342 declared_max_(maximum) { 457 declared_max_(maximum) {
343 if (ranges) 458 if (ranges)
344 samples_.reset(new SampleVector(HashMetricName(name), ranges)); 459 samples_.reset(new SampleVector(HashMetricName(name), ranges));
345 } 460 }
346 461
462 Histogram::Histogram(const std::string& name,
463 Sample minimum,
464 Sample maximum,
465 const BucketRanges* ranges,
466 HistogramBase::AtomicCount* counts,
467 size_t counts_size,
468 HistogramSamples::Metadata* meta)
469 : HistogramBase(name),
470 bucket_ranges_(ranges),
471 declared_min_(minimum),
472 declared_max_(maximum) {
473 if (ranges)
Alexei Svitkine (slow) 2016/01/12 21:54:44 Nit: {}'s since body is multi-line.
bcwhite 2016/01/13 13:38:29 Done.
474 samples_.reset(new SampleVector(HashMetricName(name),
475 counts, counts_size, meta, ranges));
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