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

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 Factory class to be cleaner Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Histogram is an object that aggregates statistics, and can summarize them in 5 // Histogram is an object that aggregates statistics, and can summarize them in
6 // various forms, including ASCII graphical, HTML, and numerically (as a 6 // various forms, including ASCII graphical, HTML, and numerically (as a
7 // vector of numbers corresponding to each of the aggregating buckets). 7 // vector of numbers corresponding to each of the aggregating buckets).
8 // See header file for details and examples. 8 // See header file for details and examples.
9 9
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 11
12 #include <math.h> 12 #include <math.h>
13 13
14 #include <algorithm> 14 #include <algorithm>
15 #include <string> 15 #include <string>
16 16
17 #include "base/compiler_specific.h" 17 #include "base/compiler_specific.h"
18 #include "base/debug/alias.h" 18 #include "base/debug/alias.h"
19 #include "base/logging.h" 19 #include "base/logging.h"
20 #include "base/metrics/histogram_macros.h" 20 #include "base/metrics/histogram_macros.h"
21 #include "base/metrics/histogram_persistence.h"
21 #include "base/metrics/metrics_hashes.h" 22 #include "base/metrics/metrics_hashes.h"
23 #include "base/metrics/persistent_memory_allocator.h"
22 #include "base/metrics/sample_vector.h" 24 #include "base/metrics/sample_vector.h"
23 #include "base/metrics/statistics_recorder.h" 25 #include "base/metrics/statistics_recorder.h"
24 #include "base/pickle.h" 26 #include "base/pickle.h"
25 #include "base/strings/string_util.h" 27 #include "base/strings/string_util.h"
26 #include "base/strings/stringprintf.h" 28 #include "base/strings/stringprintf.h"
27 #include "base/synchronization/lock.h" 29 #include "base/synchronization/lock.h"
28 #include "base/values.h" 30 #include "base/values.h"
29 31
30 namespace base { 32 namespace base {
31 33
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 } 78 }
77 79
78 } // namespace 80 } // namespace
79 81
80 typedef HistogramBase::Count Count; 82 typedef HistogramBase::Count Count;
81 typedef HistogramBase::Sample Sample; 83 typedef HistogramBase::Sample Sample;
82 84
83 // static 85 // static
84 const size_t Histogram::kBucketCount_MAX = 16384u; 86 const size_t Histogram::kBucketCount_MAX = 16384u;
85 87
88
89 class Histogram::Factory {
90 public:
91 Factory(const std::string& name,
92 HistogramBase::Sample minimum,
93 HistogramBase::Sample maximum,
94 size_t bucket_count,
95 int32 flags)
96 : Factory(name, HISTOGRAM, minimum, maximum, bucket_count, flags) {}
97
98 HistogramBase* Build();
99
100 protected:
101 Factory(const std::string& name,
102 HistogramType histogram_type,
103 HistogramBase::Sample minimum,
104 HistogramBase::Sample maximum,
105 size_t bucket_count,
106 int32 flags)
107 : name_(name),
108 histogram_type_(histogram_type),
109 minimum_(minimum),
110 maximum_(maximum),
111 bucket_count_(bucket_count),
112 flags_(flags) {}
113
114 virtual BucketRanges* CreateRanges() {
115 BucketRanges* ranges = new BucketRanges(bucket_count_ + 1);
116 Histogram::InitializeBucketRanges(minimum_, maximum_, ranges);
117 return ranges;
118 }
119
120 virtual HistogramBase* HeapAlloc(const BucketRanges* ranges) {
121 return new Histogram(name_, minimum_, maximum_, ranges);
122 }
123
124 virtual void FillHistogram(HistogramBase* histogram) {}
Alexei Svitkine (slow) 2015/12/21 19:32:10 Please document these methods and the class.
bcwhite 2015/12/22 20:50:38 Done.
125
126 const std::string& name_;
127 const HistogramType histogram_type_;
128 HistogramBase::Sample minimum_;
129 HistogramBase::Sample maximum_;
130 size_t bucket_count_;
131 int32 flags_;
132 };
Alexei Svitkine (slow) 2015/12/21 19:32:10 Add a private: section and DISALLOW_COPY_AND_ASSIG
bcwhite 2015/12/22 20:50:37 Done.
133
134 HistogramBase* Histogram::Factory::Build() {
135 ImportPersistentHistograms();
136
137 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name_);
138 if (!histogram) {
139 // To avoid racy destruction at shutdown, the following will be leaked.
140 const BucketRanges* created_ranges = CreateRanges();
141 const BucketRanges* registered_ranges =
142 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(created_ranges);
143
144 // Sometimes the bucket info is dynamically determined in create_ranges().
Alexei Svitkine (slow) 2015/12/21 19:32:10 Nit: create_ranges() -> CreateRanges().
bcwhite 2015/12/22 20:50:37 Done.
145 if (bucket_count_ == 0) {
146 bucket_count_ = registered_ranges->bucket_count();
147 minimum_ = registered_ranges->range(1);
148 maximum_ = registered_ranges->range(bucket_count_ - 1);
149 }
150
151 PersistentMemoryAllocator::Reference histogram_ref = 0;
152 HistogramBase* tentative_histogram = nullptr;
153 PersistentMemoryAllocator* allocator =
154 GetPersistentHistogramMemoryAllocator();
155 if (allocator) {
156 flags_ |= HistogramBase::kIsPersistent;
157 tentative_histogram = AllocatePersistentHistogram(
158 allocator,
159 histogram_type_,
160 name_,
161 minimum_,
162 maximum_,
163 registered_ranges,
164 flags_,
165 &histogram_ref);
166 }
167 if (!tentative_histogram) {
Alexei Svitkine (slow) 2015/12/21 19:32:10 Either make this an else or mention in what legit
bcwhite 2015/12/22 20:50:38 Done.
168 flags_ &= ~HistogramBase::kIsPersistent;
169 tentative_histogram = HeapAlloc(registered_ranges);
Alexei Svitkine (slow) 2015/12/21 19:32:10 Should this also clear histogram_ref? Or is the e
bcwhite 2015/12/22 20:50:37 Done.
170 }
171
172 FillHistogram(tentative_histogram);
173
174 tentative_histogram->SetFlags(flags_);
Alexei Svitkine (slow) 2015/12/21 19:32:10 Nit: Move this about FillHistogram() and don't sep
bcwhite 2015/12/22 20:50:37 That will require that any overriden FillHistogram
175 histogram =
176 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
177
178 // Persistent histograms need some follow-up processing.
179 if (histogram_ref) {
180 // If the created persistent histogram is canonical then it needs to be
181 // marked as "iterable" in order to be found by other processes.
182 if (histogram == tentative_histogram)
183 GetPersistentHistogramMemoryAllocator()->MakeIterable(histogram_ref);
184 // If it's not the canonical one then a race condition must have caused
185 // two to be created. The allocator does not support releasing the
186 // acquired memory so just change the type to be empty.
187 else
188 GetPersistentHistogramMemoryAllocator()->SetType(histogram_ref, 0);
Alexei Svitkine (slow) 2015/12/21 19:32:11 Can this logic be contained in the allocator? i.e.
bcwhite 2015/12/22 20:50:38 Done.
189 }
190 }
191
192 DCHECK_EQ(histogram_type_, histogram->GetHistogramType());
193 if (bucket_count_ != 0 &&
194 !histogram->HasConstructionArguments(minimum_, maximum_, bucket_count_)) {
195 // The construction arguments do not match the existing histogram. This can
196 // come about if an extension updates in the middle of a chrome run and has
197 // changed one of them, or simply by bad code within Chrome itself. We
198 // return NULL here with the expectation that bad code in Chrome will crash
199 // on dereference, but extension/Pepper APIs will guard against NULL and not
200 // crash.
201 DLOG(ERROR) << "Histogram " << name_ << " has bad construction arguments";
202 return nullptr;
203 }
204 return histogram;
205 }
206
207
86 HistogramBase* Histogram::FactoryGet(const std::string& name, 208 HistogramBase* Histogram::FactoryGet(const std::string& name,
87 Sample minimum, 209 Sample minimum,
88 Sample maximum, 210 Sample maximum,
89 size_t bucket_count, 211 size_t bucket_count,
90 int32 flags) { 212 int32 flags) {
91 bool valid_arguments = 213 bool valid_arguments =
92 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count); 214 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count);
93 DCHECK(valid_arguments); 215 DCHECK(valid_arguments);
94 216
95 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 217 return Factory(name, minimum, maximum, bucket_count, flags).Build();
96 if (!histogram) {
97 // To avoid racy destruction at shutdown, the following will be leaked.
98 BucketRanges* ranges = new BucketRanges(bucket_count + 1);
99 InitializeBucketRanges(minimum, maximum, ranges);
100 const BucketRanges* registered_ranges =
101 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
102
103 Histogram* tentative_histogram =
104 new Histogram(name, minimum, maximum, registered_ranges);
105
106 tentative_histogram->SetFlags(flags);
107 histogram =
108 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
109 }
110
111 DCHECK_EQ(HISTOGRAM, histogram->GetHistogramType());
112 if (!histogram->HasConstructionArguments(minimum, maximum, bucket_count)) {
113 // The construction arguments do not match the existing histogram. This can
114 // come about if an extension updates in the middle of a chrome run and has
115 // changed one of them, or simply by bad code within Chrome itself. We
116 // return NULL here with the expectation that bad code in Chrome will crash
117 // on dereference, but extension/Pepper APIs will guard against NULL and not
118 // crash.
119 DLOG(ERROR) << "Histogram " << name << " has bad construction arguments";
120 return NULL;
121 }
122 return histogram;
123 } 218 }
124 219
125 HistogramBase* Histogram::FactoryTimeGet(const std::string& name, 220 HistogramBase* Histogram::FactoryTimeGet(const std::string& name,
126 TimeDelta minimum, 221 TimeDelta minimum,
127 TimeDelta maximum, 222 TimeDelta maximum,
128 size_t bucket_count, 223 size_t bucket_count,
129 int32 flags) { 224 int32 flags) {
130 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()), 225 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()),
131 static_cast<Sample>(maximum.InMilliseconds()), bucket_count, 226 static_cast<Sample>(maximum.InMilliseconds()), bucket_count,
132 flags); 227 flags);
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 Sample maximum, 431 Sample maximum,
337 const BucketRanges* ranges) 432 const BucketRanges* ranges)
338 : HistogramBase(name), 433 : HistogramBase(name),
339 bucket_ranges_(ranges), 434 bucket_ranges_(ranges),
340 declared_min_(minimum), 435 declared_min_(minimum),
341 declared_max_(maximum) { 436 declared_max_(maximum) {
342 if (ranges) 437 if (ranges)
343 samples_.reset(new SampleVector(HashMetricName(name), ranges)); 438 samples_.reset(new SampleVector(HashMetricName(name), ranges));
344 } 439 }
345 440
441 Histogram::Histogram(const std::string& name,
442 Sample minimum,
443 Sample maximum,
444 const BucketRanges* ranges,
445 HistogramBase::AtomicCount* counts,
446 size_t counts_size,
447 HistogramSamples::Metadata* meta)
448 : HistogramBase(name),
449 bucket_ranges_(ranges),
450 declared_min_(minimum),
451 declared_max_(maximum) {
452 if (ranges)
453 samples_.reset(new SampleVector(HashMetricName(name),
454 counts, counts_size, meta, ranges));
455 }
456
346 Histogram::~Histogram() { 457 Histogram::~Histogram() {
347 } 458 }
348 459
349 bool Histogram::PrintEmptyBucket(size_t index) const { 460 bool Histogram::PrintEmptyBucket(size_t index) const {
350 return true; 461 return true;
351 } 462 }
352 463
353 // Use the actual bucket widths (like a linear histogram) until the widths get 464 // Use the actual bucket widths (like a linear histogram) until the widths get
354 // over some transition value, and then use that transition width. Exponentials 465 // over some transition value, and then use that transition width. Exponentials
355 // get so big so fast (and we don't expect to see a lot of entries in the large 466 // get so big so fast (and we don't expect to see a lot of entries in the large
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 ++index; 648 ++index;
538 } 649 }
539 } 650 }
540 } 651 }
541 652
542 //------------------------------------------------------------------------------ 653 //------------------------------------------------------------------------------
543 // LinearHistogram: This histogram uses a traditional set of evenly spaced 654 // LinearHistogram: This histogram uses a traditional set of evenly spaced
544 // buckets. 655 // buckets.
545 //------------------------------------------------------------------------------ 656 //------------------------------------------------------------------------------
546 657
547 LinearHistogram::~LinearHistogram() {} 658 class LinearHistogram::Factory : public Histogram::Factory {
659 public:
660 Factory(const std::string& name,
661 HistogramBase::Sample minimum,
662 HistogramBase::Sample maximum,
663 size_t bucket_count,
664 int32 flags,
665 const DescriptionPair* descriptions)
666 : Histogram::Factory(name, LINEAR_HISTOGRAM, minimum, maximum,
667 bucket_count, flags) {
668 descriptions_ = descriptions;
669 }
670
671 protected:
Alexei Svitkine (slow) 2015/12/21 19:32:10 Nit: private: and add DISALLOW_COPY_AND_ASSIGN()
bcwhite 2015/12/22 20:50:37 Done.
672 BucketRanges* CreateRanges() override {
673 BucketRanges* ranges = new BucketRanges(bucket_count_ + 1);
674 LinearHistogram::InitializeBucketRanges(minimum_, maximum_, ranges);
675 return ranges;
676 }
677
678 HistogramBase* HeapAlloc(const BucketRanges* ranges) override {
679 return new LinearHistogram(name_, minimum_, maximum_, ranges);
680 }
681
682 void FillHistogram(HistogramBase* base_histogram) override {
683 LinearHistogram* histogram = static_cast<LinearHistogram*>(base_histogram);
684 // Set range descriptions.
685 if (descriptions_) {
686 for (int i = 0; descriptions_[i].description; ++i) {
687 histogram->bucket_description_[descriptions_[i].sample] =
688 descriptions_[i].description;
689 }
690 }
691 }
692
693 const DescriptionPair* descriptions_;
694 };
548 695
549 HistogramBase* LinearHistogram::FactoryGet(const std::string& name, 696 HistogramBase* LinearHistogram::FactoryGet(const std::string& name,
550 Sample minimum, 697 Sample minimum,
551 Sample maximum, 698 Sample maximum,
552 size_t bucket_count, 699 size_t bucket_count,
553 int32 flags) { 700 int32 flags) {
554 return FactoryGetWithRangeDescription( 701 return FactoryGetWithRangeDescription(
555 name, minimum, maximum, bucket_count, flags, NULL); 702 name, minimum, maximum, bucket_count, flags, NULL);
556 } 703 }
557 704
(...skipping 28 matching lines...) Expand all
586 const std::string& name, 733 const std::string& name,
587 Sample minimum, 734 Sample minimum,
588 Sample maximum, 735 Sample maximum,
589 size_t bucket_count, 736 size_t bucket_count,
590 int32 flags, 737 int32 flags,
591 const DescriptionPair descriptions[]) { 738 const DescriptionPair descriptions[]) {
592 bool valid_arguments = Histogram::InspectConstructionArguments( 739 bool valid_arguments = Histogram::InspectConstructionArguments(
593 name, &minimum, &maximum, &bucket_count); 740 name, &minimum, &maximum, &bucket_count);
594 DCHECK(valid_arguments); 741 DCHECK(valid_arguments);
595 742
596 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 743 return Factory(name, minimum, maximum, bucket_count, flags, descriptions)
597 if (!histogram) { 744 .Build();
598 // To avoid racy destruction at shutdown, the following will be leaked.
599 BucketRanges* ranges = new BucketRanges(bucket_count + 1);
600 InitializeBucketRanges(minimum, maximum, ranges);
601 const BucketRanges* registered_ranges =
602 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
603
604 LinearHistogram* tentative_histogram =
605 new LinearHistogram(name, minimum, maximum, registered_ranges);
606
607 // Set range descriptions.
608 if (descriptions) {
609 for (int i = 0; descriptions[i].description; ++i) {
610 tentative_histogram->bucket_description_[descriptions[i].sample] =
611 descriptions[i].description;
612 }
613 }
614
615 tentative_histogram->SetFlags(flags);
616 histogram =
617 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
618 }
619
620 DCHECK_EQ(LINEAR_HISTOGRAM, histogram->GetHistogramType());
621 if (!histogram->HasConstructionArguments(minimum, maximum, bucket_count)) {
622 // The construction arguments do not match the existing histogram. This can
623 // come about if an extension updates in the middle of a chrome run and has
624 // changed one of them, or simply by bad code within Chrome itself. We
625 // return NULL here with the expectation that bad code in Chrome will crash
626 // on dereference, but extension/Pepper APIs will guard against NULL and not
627 // crash.
628 DLOG(ERROR) << "Histogram " << name << " has bad construction arguments";
629 return NULL;
630 }
631 return histogram;
632 } 745 }
633 746
634 HistogramType LinearHistogram::GetHistogramType() const { 747 HistogramType LinearHistogram::GetHistogramType() const {
635 return LINEAR_HISTOGRAM; 748 return LINEAR_HISTOGRAM;
636 } 749 }
637 750
638 LinearHistogram::LinearHistogram(const std::string& name, 751 LinearHistogram::LinearHistogram(const std::string& name,
639 Sample minimum, 752 Sample minimum,
640 Sample maximum, 753 Sample maximum,
641 const BucketRanges* ranges) 754 const BucketRanges* ranges)
642 : Histogram(name, minimum, maximum, ranges) { 755 : Histogram(name, minimum, maximum, ranges) {
643 } 756 }
644 757
758 LinearHistogram::LinearHistogram(const std::string& name,
759 Sample minimum,
760 Sample maximum,
761 const BucketRanges* ranges,
762 HistogramBase::AtomicCount* counts,
763 size_t counts_size,
764 HistogramSamples::Metadata* meta)
765 : Histogram(name,
766 minimum,
767 maximum,
768 ranges,
769 counts,
770 counts_size,
771 meta) {}
772
645 double LinearHistogram::GetBucketSize(Count current, size_t i) const { 773 double LinearHistogram::GetBucketSize(Count current, size_t i) const {
646 DCHECK_GT(ranges(i + 1), ranges(i)); 774 DCHECK_GT(ranges(i + 1), ranges(i));
647 // Adjacent buckets with different widths would have "surprisingly" many (few) 775 // Adjacent buckets with different widths would have "surprisingly" many (few)
648 // samples in a histogram if we didn't normalize this way. 776 // samples in a histogram if we didn't normalize this way.
649 double denominator = ranges(i + 1) - ranges(i); 777 double denominator = ranges(i + 1) - ranges(i);
650 return current/denominator; 778 return current/denominator;
651 } 779 }
652 780
653 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const { 781 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const {
654 int range = ranges(i); 782 int range = ranges(i);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 // The serialized histogram might be corrupted. 826 // The serialized histogram might be corrupted.
699 return NULL; 827 return NULL;
700 } 828 }
701 return histogram; 829 return histogram;
702 } 830 }
703 831
704 //------------------------------------------------------------------------------ 832 //------------------------------------------------------------------------------
705 // This section provides implementation for BooleanHistogram. 833 // This section provides implementation for BooleanHistogram.
706 //------------------------------------------------------------------------------ 834 //------------------------------------------------------------------------------
707 835
836 class BooleanHistogram::Factory : public Histogram::Factory {
837 public:
838 Factory(const std::string& name, int32 flags)
839 : Histogram::Factory(name, BOOLEAN_HISTOGRAM, 1, 2, 3, flags) {}
840
841 protected:
842 BucketRanges* CreateRanges() {
Alexei Svitkine (slow) 2015/12/21 19:32:10 Can this class just extend LinearHistogram and avo
bcwhite 2015/12/22 20:50:37 Yes but it would involve changing the LinearHistog
843 BucketRanges* ranges = new BucketRanges(3 + 1);
844 LinearHistogram::InitializeBucketRanges(1, 2, ranges);
845 return ranges;
846 }
847
848 HistogramBase* HeapAlloc(const BucketRanges* ranges) override {
849 return new BooleanHistogram(name_, ranges);
850 }
851 };
852
708 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name, 853 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name,
709 int32 flags) { 854 int32 flags) {
710 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 855 return Factory(name, flags).Build();
711 if (!histogram) {
712 // To avoid racy destruction at shutdown, the following will be leaked.
713 BucketRanges* ranges = new BucketRanges(4);
714 LinearHistogram::InitializeBucketRanges(1, 2, ranges);
715 const BucketRanges* registered_ranges =
716 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
717
718 BooleanHistogram* tentative_histogram =
719 new BooleanHistogram(name, registered_ranges);
720
721 tentative_histogram->SetFlags(flags);
722 histogram =
723 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
724 }
725
726 DCHECK_EQ(BOOLEAN_HISTOGRAM, histogram->GetHistogramType());
727 return histogram;
728 } 856 }
729 857
730 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32 flags) { 858 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32 flags) {
731 return FactoryGet(std::string(name), flags); 859 return FactoryGet(std::string(name), flags);
732 } 860 }
733 861
734 HistogramType BooleanHistogram::GetHistogramType() const { 862 HistogramType BooleanHistogram::GetHistogramType() const {
735 return BOOLEAN_HISTOGRAM; 863 return BOOLEAN_HISTOGRAM;
736 } 864 }
737 865
738 BooleanHistogram::BooleanHistogram(const std::string& name, 866 BooleanHistogram::BooleanHistogram(const std::string& name,
739 const BucketRanges* ranges) 867 const BucketRanges* ranges)
740 : LinearHistogram(name, 1, 2, ranges) {} 868 : LinearHistogram(name, 1, 2, ranges) {}
741 869
870 BooleanHistogram::BooleanHistogram(const std::string& name,
871 const BucketRanges* ranges,
872 HistogramBase::AtomicCount* counts,
873 HistogramSamples::Metadata* meta)
874 : LinearHistogram(name, 1, 2, ranges, counts, 2, meta) {}
875
742 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { 876 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) {
743 std::string histogram_name; 877 std::string histogram_name;
744 int flags; 878 int flags;
745 int declared_min; 879 int declared_min;
746 int declared_max; 880 int declared_max;
747 size_t bucket_count; 881 size_t bucket_count;
748 uint32 range_checksum; 882 uint32 range_checksum;
749 883
750 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, 884 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min,
751 &declared_max, &bucket_count, &range_checksum)) { 885 &declared_max, &bucket_count, &range_checksum)) {
752 return NULL; 886 return NULL;
753 } 887 }
754 888
755 HistogramBase* histogram = BooleanHistogram::FactoryGet( 889 HistogramBase* histogram = BooleanHistogram::FactoryGet(
756 histogram_name, flags); 890 histogram_name, flags);
757 if (!ValidateRangeChecksum(*histogram, range_checksum)) { 891 if (!ValidateRangeChecksum(*histogram, range_checksum)) {
758 // The serialized histogram might be corrupted. 892 // The serialized histogram might be corrupted.
759 return NULL; 893 return NULL;
760 } 894 }
761 return histogram; 895 return histogram;
762 } 896 }
763 897
764 //------------------------------------------------------------------------------ 898 //------------------------------------------------------------------------------
765 // CustomHistogram: 899 // CustomHistogram:
766 //------------------------------------------------------------------------------ 900 //------------------------------------------------------------------------------
767 901
902 class CustomHistogram::Factory : public Histogram::Factory {
903 public:
904 Factory(const std::string& name,
905 const std::vector<Sample>* custom_ranges,
906 int32 flags)
907 : Histogram::Factory(name, CUSTOM_HISTOGRAM, 0, 0, 0, flags) {
908 custom_ranges_ = custom_ranges;
909 }
910
911 protected:
912 BucketRanges* CreateRanges() {
913 // Remove the duplicates in the custom ranges array.
914 std::vector<int> ranges = *custom_ranges_;
915 ranges.push_back(0); // Ensure we have a zero value.
916 ranges.push_back(HistogramBase::kSampleType_MAX);
917 std::sort(ranges.begin(), ranges.end());
918 ranges.erase(std::unique(ranges.begin(), ranges.end()), ranges.end());
919
920 BucketRanges* bucket_ranges = new BucketRanges(ranges.size());
921 for (size_t i = 0; i < ranges.size(); i++) {
922 bucket_ranges->set_range(i, ranges[i]);
923 }
924 bucket_ranges->ResetChecksum();
925 return bucket_ranges;
926 }
927
928 HistogramBase* HeapAlloc(const BucketRanges* ranges) override {
929 return new CustomHistogram(name_, ranges);
930 }
931
932 const std::vector<Sample>* custom_ranges_;
933 };
934
768 HistogramBase* CustomHistogram::FactoryGet( 935 HistogramBase* CustomHistogram::FactoryGet(
769 const std::string& name, 936 const std::string& name,
770 const std::vector<Sample>& custom_ranges, 937 const std::vector<Sample>& custom_ranges,
771 int32 flags) { 938 int32 flags) {
772 CHECK(ValidateCustomRanges(custom_ranges)); 939 CHECK(ValidateCustomRanges(custom_ranges));
773 940
774 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 941 return Factory(name, &custom_ranges, flags).Build();
775 if (!histogram) {
776 BucketRanges* ranges = CreateBucketRangesFromCustomRanges(custom_ranges);
777 const BucketRanges* registered_ranges =
778 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
779
780 // To avoid racy destruction at shutdown, the following will be leaked.
781 CustomHistogram* tentative_histogram =
782 new CustomHistogram(name, registered_ranges);
783
784 tentative_histogram->SetFlags(flags);
785
786 histogram =
787 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
788 }
789
790 DCHECK_EQ(histogram->GetHistogramType(), CUSTOM_HISTOGRAM);
791 return histogram;
792 } 942 }
793 943
794 HistogramBase* CustomHistogram::FactoryGet( 944 HistogramBase* CustomHistogram::FactoryGet(
795 const char* name, 945 const char* name,
796 const std::vector<Sample>& custom_ranges, 946 const std::vector<Sample>& custom_ranges,
797 int32 flags) { 947 int32 flags) {
798 return FactoryGet(std::string(name), custom_ranges, flags); 948 return FactoryGet(std::string(name), custom_ranges, flags);
799 } 949 }
800 950
801 HistogramType CustomHistogram::GetHistogramType() const { 951 HistogramType CustomHistogram::GetHistogramType() const {
(...skipping 15 matching lines...) Expand all
817 return all_values; 967 return all_values;
818 } 968 }
819 969
820 CustomHistogram::CustomHistogram(const std::string& name, 970 CustomHistogram::CustomHistogram(const std::string& name,
821 const BucketRanges* ranges) 971 const BucketRanges* ranges)
822 : Histogram(name, 972 : Histogram(name,
823 ranges->range(1), 973 ranges->range(1),
824 ranges->range(ranges->bucket_count() - 1), 974 ranges->range(ranges->bucket_count() - 1),
825 ranges) {} 975 ranges) {}
826 976
977 CustomHistogram::CustomHistogram(const std::string& name,
978 const BucketRanges* ranges,
979 HistogramBase::AtomicCount* counts,
980 size_t counts_size,
981 HistogramSamples::Metadata* meta)
982 : Histogram(name,
983 ranges->range(1),
984 ranges->range(ranges->bucket_count() - 1),
985 ranges,
986 counts,
987 counts_size,
988 meta) {}
989
827 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { 990 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const {
828 if (!Histogram::SerializeInfoImpl(pickle)) 991 if (!Histogram::SerializeInfoImpl(pickle))
829 return false; 992 return false;
830 993
831 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't 994 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't
832 // write them. 995 // write them.
833 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { 996 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) {
834 if (!pickle->WriteInt(bucket_ranges()->range(i))) 997 if (!pickle->WriteInt(bucket_ranges()->range(i)))
835 return false; 998 return false;
836 } 999 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
879 for (size_t i = 0; i < custom_ranges.size(); i++) { 1042 for (size_t i = 0; i < custom_ranges.size(); i++) {
880 Sample sample = custom_ranges[i]; 1043 Sample sample = custom_ranges[i];
881 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) 1044 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1)
882 return false; 1045 return false;
883 if (sample != 0) 1046 if (sample != 0)
884 has_valid_range = true; 1047 has_valid_range = true;
885 } 1048 }
886 return has_valid_range; 1049 return has_valid_range;
887 } 1050 }
888 1051
889 // static
890 BucketRanges* CustomHistogram::CreateBucketRangesFromCustomRanges(
891 const std::vector<Sample>& custom_ranges) {
892 // Remove the duplicates in the custom ranges array.
893 std::vector<int> ranges = custom_ranges;
894 ranges.push_back(0); // Ensure we have a zero value.
895 ranges.push_back(HistogramBase::kSampleType_MAX);
896 std::sort(ranges.begin(), ranges.end());
897 ranges.erase(std::unique(ranges.begin(), ranges.end()), ranges.end());
898
899 BucketRanges* bucket_ranges = new BucketRanges(ranges.size());
900 for (size_t i = 0; i < ranges.size(); i++) {
901 bucket_ranges->set_range(i, ranges[i]);
902 }
903 bucket_ranges->ResetChecksum();
904 return bucket_ranges;
905 }
906
907 } // namespace base 1052 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698