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

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: rebased 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
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);
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 Sample maximum, 441 Sample maximum,
338 const BucketRanges* ranges) 442 const BucketRanges* ranges)
339 : HistogramBase(name), 443 : HistogramBase(name),
340 bucket_ranges_(ranges), 444 bucket_ranges_(ranges),
341 declared_min_(minimum), 445 declared_min_(minimum),
342 declared_max_(maximum) { 446 declared_max_(maximum) {
343 if (ranges) 447 if (ranges)
344 samples_.reset(new SampleVector(HashMetricName(name), ranges)); 448 samples_.reset(new SampleVector(HashMetricName(name), ranges));
345 } 449 }
346 450
451 Histogram::Histogram(const std::string& name,
452 Sample minimum,
453 Sample maximum,
454 const BucketRanges* ranges,
455 HistogramBase::AtomicCount* counts,
456 size_t counts_size,
457 HistogramSamples::Metadata* meta)
458 : HistogramBase(name),
459 bucket_ranges_(ranges),
460 declared_min_(minimum),
461 declared_max_(maximum) {
462 if (ranges)
463 samples_.reset(new SampleVector(HashMetricName(name),
464 counts, counts_size, meta, ranges));
465 }
466
347 Histogram::~Histogram() { 467 Histogram::~Histogram() {
348 } 468 }
349 469
350 bool Histogram::PrintEmptyBucket(size_t index) const { 470 bool Histogram::PrintEmptyBucket(size_t index) const {
351 return true; 471 return true;
352 } 472 }
353 473
354 // Use the actual bucket widths (like a linear histogram) until the widths get 474 // 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 475 // 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 476 // 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; 658 ++index;
539 } 659 }
540 } 660 }
541 } 661 }
542 662
543 //------------------------------------------------------------------------------ 663 //------------------------------------------------------------------------------
544 // LinearHistogram: This histogram uses a traditional set of evenly spaced 664 // LinearHistogram: This histogram uses a traditional set of evenly spaced
545 // buckets. 665 // buckets.
546 //------------------------------------------------------------------------------ 666 //------------------------------------------------------------------------------
547 667
668 class LinearHistogram::Factory : public Histogram::Factory {
669 public:
670 Factory(const std::string& name,
671 HistogramBase::Sample minimum,
672 HistogramBase::Sample maximum,
673 size_t bucket_count,
674 int32_t flags,
675 const DescriptionPair* descriptions)
676 : Histogram::Factory(name, LINEAR_HISTOGRAM, minimum, maximum,
677 bucket_count, flags) {
678 descriptions_ = descriptions;
679 }
680
681 protected:
682 BucketRanges* CreateRanges() override {
683 BucketRanges* ranges = new BucketRanges(bucket_count_ + 1);
684 LinearHistogram::InitializeBucketRanges(minimum_, maximum_, ranges);
685 return ranges;
686 }
687
688 HistogramBase* HeapAlloc(const BucketRanges* ranges) override {
689 return new LinearHistogram(name_, minimum_, maximum_, ranges);
690 }
691
692 void FillHistogram(HistogramBase* base_histogram) override {
693 Histogram::Factory::FillHistogram(base_histogram);
694 LinearHistogram* histogram = static_cast<LinearHistogram*>(base_histogram);
695 // Set range descriptions.
696 if (descriptions_) {
697 for (int i = 0; descriptions_[i].description; ++i) {
698 histogram->bucket_description_[descriptions_[i].sample] =
699 descriptions_[i].description;
700 }
701 }
702 }
703
704 private:
705 const DescriptionPair* descriptions_;
706 DISALLOW_COPY_AND_ASSIGN(Factory);
707 };
708
548 LinearHistogram::~LinearHistogram() {} 709 LinearHistogram::~LinearHistogram() {}
549 710
550 HistogramBase* LinearHistogram::FactoryGet(const std::string& name, 711 HistogramBase* LinearHistogram::FactoryGet(const std::string& name,
551 Sample minimum, 712 Sample minimum,
552 Sample maximum, 713 Sample maximum,
553 size_t bucket_count, 714 size_t bucket_count,
554 int32_t flags) { 715 int32_t flags) {
555 return FactoryGetWithRangeDescription( 716 return FactoryGetWithRangeDescription(
556 name, minimum, maximum, bucket_count, flags, NULL); 717 name, minimum, maximum, bucket_count, flags, NULL);
557 } 718 }
(...skipping 29 matching lines...) Expand all
587 const std::string& name, 748 const std::string& name,
588 Sample minimum, 749 Sample minimum,
589 Sample maximum, 750 Sample maximum,
590 size_t bucket_count, 751 size_t bucket_count,
591 int32_t flags, 752 int32_t flags,
592 const DescriptionPair descriptions[]) { 753 const DescriptionPair descriptions[]) {
593 bool valid_arguments = Histogram::InspectConstructionArguments( 754 bool valid_arguments = Histogram::InspectConstructionArguments(
594 name, &minimum, &maximum, &bucket_count); 755 name, &minimum, &maximum, &bucket_count);
595 DCHECK(valid_arguments); 756 DCHECK(valid_arguments);
596 757
597 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 758 return Factory(name, minimum, maximum, bucket_count, flags, descriptions)
598 if (!histogram) { 759 .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 } 760 }
634 761
635 HistogramType LinearHistogram::GetHistogramType() const { 762 HistogramType LinearHistogram::GetHistogramType() const {
636 return LINEAR_HISTOGRAM; 763 return LINEAR_HISTOGRAM;
637 } 764 }
638 765
639 LinearHistogram::LinearHistogram(const std::string& name, 766 LinearHistogram::LinearHistogram(const std::string& name,
640 Sample minimum, 767 Sample minimum,
641 Sample maximum, 768 Sample maximum,
642 const BucketRanges* ranges) 769 const BucketRanges* ranges)
643 : Histogram(name, minimum, maximum, ranges) { 770 : Histogram(name, minimum, maximum, ranges) {
644 } 771 }
645 772
773 LinearHistogram::LinearHistogram(const std::string& name,
774 Sample minimum,
775 Sample maximum,
776 const BucketRanges* ranges,
777 HistogramBase::AtomicCount* counts,
778 size_t counts_size,
779 HistogramSamples::Metadata* meta)
780 : Histogram(name,
781 minimum,
782 maximum,
783 ranges,
784 counts,
785 counts_size,
786 meta) {}
787
646 double LinearHistogram::GetBucketSize(Count current, size_t i) const { 788 double LinearHistogram::GetBucketSize(Count current, size_t i) const {
647 DCHECK_GT(ranges(i + 1), ranges(i)); 789 DCHECK_GT(ranges(i + 1), ranges(i));
648 // Adjacent buckets with different widths would have "surprisingly" many (few) 790 // Adjacent buckets with different widths would have "surprisingly" many (few)
649 // samples in a histogram if we didn't normalize this way. 791 // samples in a histogram if we didn't normalize this way.
650 double denominator = ranges(i + 1) - ranges(i); 792 double denominator = ranges(i + 1) - ranges(i);
651 return current/denominator; 793 return current/denominator;
652 } 794 }
653 795
654 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const { 796 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const {
655 int range = ranges(i); 797 int range = ranges(i);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 // The serialized histogram might be corrupted. 841 // The serialized histogram might be corrupted.
700 return NULL; 842 return NULL;
701 } 843 }
702 return histogram; 844 return histogram;
703 } 845 }
704 846
705 //------------------------------------------------------------------------------ 847 //------------------------------------------------------------------------------
706 // This section provides implementation for BooleanHistogram. 848 // This section provides implementation for BooleanHistogram.
707 //------------------------------------------------------------------------------ 849 //------------------------------------------------------------------------------
708 850
851 class BooleanHistogram::Factory : public Histogram::Factory {
852 public:
853 Factory(const std::string& name, int32_t flags)
854 : Histogram::Factory(name, BOOLEAN_HISTOGRAM, 1, 2, 3, flags) {}
855
856 protected:
857 BucketRanges* CreateRanges() {
858 BucketRanges* ranges = new BucketRanges(3 + 1);
859 LinearHistogram::InitializeBucketRanges(1, 2, ranges);
860 return ranges;
861 }
862
863 HistogramBase* HeapAlloc(const BucketRanges* ranges) override {
864 return new BooleanHistogram(name_, ranges);
865 }
866
867 private:
868 DISALLOW_COPY_AND_ASSIGN(Factory);
869 };
870
709 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name, 871 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name,
710 int32_t flags) { 872 int32_t flags) {
711 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 873 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 } 874 }
730 875
731 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32_t flags) { 876 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32_t flags) {
732 return FactoryGet(std::string(name), flags); 877 return FactoryGet(std::string(name), flags);
733 } 878 }
734 879
735 HistogramType BooleanHistogram::GetHistogramType() const { 880 HistogramType BooleanHistogram::GetHistogramType() const {
736 return BOOLEAN_HISTOGRAM; 881 return BOOLEAN_HISTOGRAM;
737 } 882 }
738 883
739 BooleanHistogram::BooleanHistogram(const std::string& name, 884 BooleanHistogram::BooleanHistogram(const std::string& name,
740 const BucketRanges* ranges) 885 const BucketRanges* ranges)
741 : LinearHistogram(name, 1, 2, ranges) {} 886 : LinearHistogram(name, 1, 2, ranges) {}
742 887
888 BooleanHistogram::BooleanHistogram(const std::string& name,
889 const BucketRanges* ranges,
890 HistogramBase::AtomicCount* counts,
891 HistogramSamples::Metadata* meta)
892 : LinearHistogram(name, 1, 2, ranges, counts, 2, meta) {}
893
743 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { 894 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) {
744 std::string histogram_name; 895 std::string histogram_name;
745 int flags; 896 int flags;
746 int declared_min; 897 int declared_min;
747 int declared_max; 898 int declared_max;
748 size_t bucket_count; 899 size_t bucket_count;
749 uint32_t range_checksum; 900 uint32_t range_checksum;
750 901
751 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, 902 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min,
752 &declared_max, &bucket_count, &range_checksum)) { 903 &declared_max, &bucket_count, &range_checksum)) {
753 return NULL; 904 return NULL;
754 } 905 }
755 906
756 HistogramBase* histogram = BooleanHistogram::FactoryGet( 907 HistogramBase* histogram = BooleanHistogram::FactoryGet(
757 histogram_name, flags); 908 histogram_name, flags);
758 if (!ValidateRangeChecksum(*histogram, range_checksum)) { 909 if (!ValidateRangeChecksum(*histogram, range_checksum)) {
759 // The serialized histogram might be corrupted. 910 // The serialized histogram might be corrupted.
760 return NULL; 911 return NULL;
761 } 912 }
762 return histogram; 913 return histogram;
763 } 914 }
764 915
765 //------------------------------------------------------------------------------ 916 //------------------------------------------------------------------------------
766 // CustomHistogram: 917 // CustomHistogram:
767 //------------------------------------------------------------------------------ 918 //------------------------------------------------------------------------------
768 919
920 class CustomHistogram::Factory : public Histogram::Factory {
921 public:
922 Factory(const std::string& name,
923 const std::vector<Sample>* custom_ranges,
924 int32_t flags)
925 : Histogram::Factory(name, CUSTOM_HISTOGRAM, 0, 0, 0, flags) {
926 custom_ranges_ = custom_ranges;
927 }
928
929 protected:
930 BucketRanges* CreateRanges() {
931 // Remove the duplicates in the custom ranges array.
932 std::vector<int> ranges = *custom_ranges_;
933 ranges.push_back(0); // Ensure we have a zero value.
934 ranges.push_back(HistogramBase::kSampleType_MAX);
935 std::sort(ranges.begin(), ranges.end());
936 ranges.erase(std::unique(ranges.begin(), ranges.end()), ranges.end());
937
938 BucketRanges* bucket_ranges = new BucketRanges(ranges.size());
939 for (size_t i = 0; i < ranges.size(); i++) {
940 bucket_ranges->set_range(i, ranges[i]);
941 }
942 bucket_ranges->ResetChecksum();
943 return bucket_ranges;
944 }
945
946 HistogramBase* HeapAlloc(const BucketRanges* ranges) override {
947 return new CustomHistogram(name_, ranges);
948 }
949
950 private:
951 const std::vector<Sample>* custom_ranges_;
952 DISALLOW_COPY_AND_ASSIGN(Factory);
953 };
954
769 HistogramBase* CustomHistogram::FactoryGet( 955 HistogramBase* CustomHistogram::FactoryGet(
770 const std::string& name, 956 const std::string& name,
771 const std::vector<Sample>& custom_ranges, 957 const std::vector<Sample>& custom_ranges,
772 int32_t flags) { 958 int32_t flags) {
773 CHECK(ValidateCustomRanges(custom_ranges)); 959 CHECK(ValidateCustomRanges(custom_ranges));
774 960
775 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 961 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 } 962 }
794 963
795 HistogramBase* CustomHistogram::FactoryGet( 964 HistogramBase* CustomHistogram::FactoryGet(
796 const char* name, 965 const char* name,
797 const std::vector<Sample>& custom_ranges, 966 const std::vector<Sample>& custom_ranges,
798 int32_t flags) { 967 int32_t flags) {
799 return FactoryGet(std::string(name), custom_ranges, flags); 968 return FactoryGet(std::string(name), custom_ranges, flags);
800 } 969 }
801 970
802 HistogramType CustomHistogram::GetHistogramType() const { 971 HistogramType CustomHistogram::GetHistogramType() const {
(...skipping 15 matching lines...) Expand all
818 return all_values; 987 return all_values;
819 } 988 }
820 989
821 CustomHistogram::CustomHistogram(const std::string& name, 990 CustomHistogram::CustomHistogram(const std::string& name,
822 const BucketRanges* ranges) 991 const BucketRanges* ranges)
823 : Histogram(name, 992 : Histogram(name,
824 ranges->range(1), 993 ranges->range(1),
825 ranges->range(ranges->bucket_count() - 1), 994 ranges->range(ranges->bucket_count() - 1),
826 ranges) {} 995 ranges) {}
827 996
997 CustomHistogram::CustomHistogram(const std::string& name,
998 const BucketRanges* ranges,
999 HistogramBase::AtomicCount* counts,
1000 size_t counts_size,
1001 HistogramSamples::Metadata* meta)
1002 : Histogram(name,
1003 ranges->range(1),
1004 ranges->range(ranges->bucket_count() - 1),
1005 ranges,
1006 counts,
1007 counts_size,
1008 meta) {}
1009
828 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { 1010 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const {
829 if (!Histogram::SerializeInfoImpl(pickle)) 1011 if (!Histogram::SerializeInfoImpl(pickle))
830 return false; 1012 return false;
831 1013
832 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't 1014 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't
833 // write them. 1015 // write them.
834 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { 1016 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) {
835 if (!pickle->WriteInt(bucket_ranges()->range(i))) 1017 if (!pickle->WriteInt(bucket_ranges()->range(i)))
836 return false; 1018 return false;
837 } 1019 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
880 for (size_t i = 0; i < custom_ranges.size(); i++) { 1062 for (size_t i = 0; i < custom_ranges.size(); i++) {
881 Sample sample = custom_ranges[i]; 1063 Sample sample = custom_ranges[i];
882 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) 1064 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1)
883 return false; 1065 return false;
884 if (sample != 0) 1066 if (sample != 0)
885 has_valid_range = true; 1067 has_valid_range = true;
886 } 1068 }
887 return has_valid_range; 1069 return has_valid_range;
888 } 1070 }
889 1071
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 1072 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698