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

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: added a couple tests (and fixed related issues) 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/memory/persistent_memory_allocator.h"
20 #include "base/metrics/histogram_macros.h" 21 #include "base/metrics/histogram_macros.h"
21 #include "base/metrics/metrics_hashes.h" 22 #include "base/metrics/metrics_hashes.h"
22 #include "base/metrics/sample_vector.h" 23 #include "base/metrics/sample_vector.h"
23 #include "base/metrics/statistics_recorder.h" 24 #include "base/metrics/statistics_recorder.h"
24 #include "base/pickle.h" 25 #include "base/pickle.h"
25 #include "base/strings/string_util.h" 26 #include "base/strings/string_util.h"
26 #include "base/strings/stringprintf.h" 27 #include "base/strings/stringprintf.h"
27 #include "base/synchronization/lock.h" 28 #include "base/synchronization/lock.h"
28 #include "base/values.h" 29 #include "base/values.h"
29 30
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 const size_t Histogram::kBucketCount_MAX = 16384u; 85 const size_t Histogram::kBucketCount_MAX = 16384u;
85 86
86 HistogramBase* Histogram::FactoryGet(const std::string& name, 87 HistogramBase* Histogram::FactoryGet(const std::string& name,
87 Sample minimum, 88 Sample minimum,
88 Sample maximum, 89 Sample maximum,
89 size_t bucket_count, 90 size_t bucket_count,
90 int32 flags) { 91 int32 flags) {
91 bool valid_arguments = 92 bool valid_arguments =
92 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count); 93 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count);
93 DCHECK(valid_arguments); 94 DCHECK(valid_arguments);
95 ImportPersistentHistograms();
94 96
95 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 97 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
96 if (!histogram) { 98 if (!histogram) {
97 // To avoid racy destruction at shutdown, the following will be leaked. 99 // To avoid racy destruction at shutdown, the following will be leaked.
98 BucketRanges* ranges = new BucketRanges(bucket_count + 1); 100 BucketRanges* ranges = new BucketRanges(bucket_count + 1);
99 InitializeBucketRanges(minimum, maximum, ranges); 101 InitializeBucketRanges(minimum, maximum, ranges);
100 const BucketRanges* registered_ranges = 102 const BucketRanges* registered_ranges =
101 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); 103 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
102 104
103 Histogram* tentative_histogram = 105 PersistentMemoryAllocator::Reference histogram_ref = 0;
104 new Histogram(name, minimum, maximum, registered_ranges); 106 HistogramBase* tentative_histogram = nullptr;
107 if (allocator_) {
108 flags |= kIsPersistent;
109 tentative_histogram = AllocatePersistentHistogram(
110 GetDefaultPersistentMemoryAllocator(),
111 HISTOGRAM,
112 name,
113 minimum,
114 maximum,
115 registered_ranges,
116 flags,
117 &histogram_ref);
118 }
119 if (!tentative_histogram) {
120 flags &= ~kIsPersistent;
121 tentative_histogram = new Histogram(
122 name, minimum, maximum, registered_ranges);
123 }
105 124
106 tentative_histogram->SetFlags(flags); 125 tentative_histogram->SetFlags(flags);
107 histogram = 126 histogram =
108 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); 127 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
128
129 // Persistent histograms need some follow-up processing.
130 if (histogram_ref) {
131 // If the created persistent histogram is canonical then it needs to be
132 // marked as "iterable" in order to be found by other processes.
133 if (histogram == tentative_histogram)
134 GetDefaultPersistentMemoryAllocator()->MakeIterable(histogram_ref);
135 // If it's not the canonical one then a race condition must have caused
136 // two to be created. The allocator does not support releasing the
137 // acquired memory so just change the type to be empty.
138 else
139 GetDefaultPersistentMemoryAllocator()->SetType(histogram_ref, 0);
140 }
109 } 141 }
110 142
111 DCHECK_EQ(HISTOGRAM, histogram->GetHistogramType()); 143 DCHECK_EQ(HISTOGRAM, histogram->GetHistogramType());
112 if (!histogram->HasConstructionArguments(minimum, maximum, bucket_count)) { 144 if (!histogram->HasConstructionArguments(minimum, maximum, bucket_count)) {
113 // The construction arguments do not match the existing histogram. This can 145 // 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 146 // 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 147 // 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 148 // 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 149 // on dereference, but extension/Pepper APIs will guard against NULL and not
118 // crash. 150 // crash.
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 Sample maximum, 369 Sample maximum,
338 const BucketRanges* ranges) 370 const BucketRanges* ranges)
339 : HistogramBase(name), 371 : HistogramBase(name),
340 bucket_ranges_(ranges), 372 bucket_ranges_(ranges),
341 declared_min_(minimum), 373 declared_min_(minimum),
342 declared_max_(maximum) { 374 declared_max_(maximum) {
343 if (ranges) 375 if (ranges)
344 samples_.reset(new SampleVector(HashMetricName(name), ranges)); 376 samples_.reset(new SampleVector(HashMetricName(name), ranges));
345 } 377 }
346 378
379 Histogram::Histogram(const std::string& name,
380 Sample minimum,
381 Sample maximum,
382 const BucketRanges* ranges,
383 HistogramBase::AtomicCount* counts,
384 size_t counts_size,
385 HistogramSamples::Metadata* meta)
386 : HistogramBase(name),
387 bucket_ranges_(ranges),
388 declared_min_(minimum),
389 declared_max_(maximum) {
390 if (ranges)
391 samples_.reset(new SampleVector(HashMetricName(name),
392 counts, counts_size, meta, ranges));
393 }
394
347 Histogram::~Histogram() { 395 Histogram::~Histogram() {
348 } 396 }
349 397
350 bool Histogram::PrintEmptyBucket(size_t index) const { 398 bool Histogram::PrintEmptyBucket(size_t index) const {
351 return true; 399 return true;
352 } 400 }
353 401
354 // Use the actual bucket widths (like a linear histogram) until the widths get 402 // 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 403 // 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 404 // get so big so fast (and we don't expect to see a lot of entries in the large
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 440
393 if (!ValidateRangeChecksum(*histogram, range_checksum)) { 441 if (!ValidateRangeChecksum(*histogram, range_checksum)) {
394 // The serialized histogram might be corrupted. 442 // The serialized histogram might be corrupted.
395 return NULL; 443 return NULL;
396 } 444 }
397 return histogram; 445 return histogram;
398 } 446 }
399 447
400 scoped_ptr<SampleVector> Histogram::SnapshotSampleVector() const { 448 scoped_ptr<SampleVector> Histogram::SnapshotSampleVector() const {
401 scoped_ptr<SampleVector> samples( 449 scoped_ptr<SampleVector> samples(
402 new SampleVector(HashMetricName(histogram_name()), bucket_ranges())); 450 new SampleVector(HashMetricName(histogram_name()),
451 bucket_ranges()));
403 samples->Add(*samples_); 452 samples->Add(*samples_);
404 return samples; 453 return samples;
405 } 454 }
406 455
407 void Histogram::WriteAsciiImpl(bool graph_it, 456 void Histogram::WriteAsciiImpl(bool graph_it,
408 const std::string& newline, 457 const std::string& newline,
409 std::string* output) const { 458 std::string* output) const {
410 // Get local (stack) copies of all effectively volatile class data so that we 459 // Get local (stack) copies of all effectively volatile class data so that we
411 // are consistent across our output activities. 460 // are consistent across our output activities.
412 scoped_ptr<SampleVector> snapshot = SnapshotSampleVector(); 461 scoped_ptr<SampleVector> snapshot = SnapshotSampleVector();
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( 635 HistogramBase* LinearHistogram::FactoryGetWithRangeDescription(
587 const std::string& name, 636 const std::string& name,
588 Sample minimum, 637 Sample minimum,
589 Sample maximum, 638 Sample maximum,
590 size_t bucket_count, 639 size_t bucket_count,
591 int32 flags, 640 int32 flags,
592 const DescriptionPair descriptions[]) { 641 const DescriptionPair descriptions[]) {
593 bool valid_arguments = Histogram::InspectConstructionArguments( 642 bool valid_arguments = Histogram::InspectConstructionArguments(
594 name, &minimum, &maximum, &bucket_count); 643 name, &minimum, &maximum, &bucket_count);
595 DCHECK(valid_arguments); 644 DCHECK(valid_arguments);
645 ImportPersistentHistograms();
596 646
597 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 647 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
598 if (!histogram) { 648 if (!histogram) {
599 // To avoid racy destruction at shutdown, the following will be leaked. 649 // To avoid racy destruction at shutdown, the following will be leaked.
600 BucketRanges* ranges = new BucketRanges(bucket_count + 1); 650 BucketRanges* ranges = new BucketRanges(bucket_count + 1);
601 InitializeBucketRanges(minimum, maximum, ranges); 651 InitializeBucketRanges(minimum, maximum, ranges);
602 const BucketRanges* registered_ranges = 652 const BucketRanges* registered_ranges =
603 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); 653 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
604 654
605 LinearHistogram* tentative_histogram = 655 PersistentMemoryAllocator::Reference histogram_ref = 0;
606 new LinearHistogram(name, minimum, maximum, registered_ranges); 656 LinearHistogram* tentative_histogram = nullptr;
657 if (allocator_) {
658 flags |= kIsPersistent;
659 tentative_histogram = static_cast<LinearHistogram*>(
660 AllocatePersistentHistogram(
661 GetDefaultPersistentMemoryAllocator(),
662 LINEAR_HISTOGRAM,
663 name,
664 minimum,
665 maximum,
666 registered_ranges,
667 flags,
668 &histogram_ref));
669 }
670 if (!tentative_histogram) {
671 flags &= ~kIsPersistent;
672 tentative_histogram = new LinearHistogram(
673 name, minimum, maximum, registered_ranges);
674 }
607 675
608 // Set range descriptions. 676 // Set range descriptions.
609 if (descriptions) { 677 if (descriptions) {
610 for (int i = 0; descriptions[i].description; ++i) { 678 for (int i = 0; descriptions[i].description; ++i) {
611 tentative_histogram->bucket_description_[descriptions[i].sample] = 679 tentative_histogram->bucket_description_[descriptions[i].sample] =
612 descriptions[i].description; 680 descriptions[i].description;
613 } 681 }
614 } 682 }
615 683
616 tentative_histogram->SetFlags(flags); 684 tentative_histogram->SetFlags(flags);
617 histogram = 685 histogram =
618 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); 686 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
687
688 // Persistent histograms need some follow-up processing.
689 if (histogram_ref) {
690 // If the created persistent histogram is canonical then it needs to be
691 // marked as "iterable" in order to be found by other processes.
692 if (histogram == tentative_histogram)
693 GetDefaultPersistentMemoryAllocator()->MakeIterable(histogram_ref);
694 // If it's not the canonical one then a race condition must have caused
695 // two to be created. The allocator does not support releasing the
696 // acquired memory so just change the type to be empty.
697 else
698 GetDefaultPersistentMemoryAllocator()->SetType(histogram_ref, 0);
699 }
619 } 700 }
620 701
621 DCHECK_EQ(LINEAR_HISTOGRAM, histogram->GetHistogramType()); 702 DCHECK_EQ(LINEAR_HISTOGRAM, histogram->GetHistogramType());
622 if (!histogram->HasConstructionArguments(minimum, maximum, bucket_count)) { 703 if (!histogram->HasConstructionArguments(minimum, maximum, bucket_count)) {
623 // The construction arguments do not match the existing histogram. This can 704 // 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 705 // 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 706 // 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 707 // 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 708 // on dereference, but extension/Pepper APIs will guard against NULL and not
628 // crash. 709 // crash.
629 DLOG(ERROR) << "Histogram " << name << " has bad construction arguments"; 710 DLOG(ERROR) << "Histogram " << name << " has bad construction arguments";
630 return NULL; 711 return NULL;
631 } 712 }
632 return histogram; 713 return histogram;
633 } 714 }
634 715
635 HistogramType LinearHistogram::GetHistogramType() const { 716 HistogramType LinearHistogram::GetHistogramType() const {
636 return LINEAR_HISTOGRAM; 717 return LINEAR_HISTOGRAM;
637 } 718 }
638 719
639 LinearHistogram::LinearHistogram(const std::string& name, 720 LinearHistogram::LinearHistogram(const std::string& name,
640 Sample minimum, 721 Sample minimum,
641 Sample maximum, 722 Sample maximum,
642 const BucketRanges* ranges) 723 const BucketRanges* ranges)
643 : Histogram(name, minimum, maximum, ranges) { 724 : Histogram(name, minimum, maximum, ranges) {
644 } 725 }
645 726
727 LinearHistogram::LinearHistogram(const std::string& name,
728 Sample minimum,
729 Sample maximum,
730 const BucketRanges* ranges,
731 HistogramBase::AtomicCount* counts,
732 size_t counts_size,
733 HistogramSamples::Metadata* meta)
734 : Histogram(name,
735 minimum,
736 maximum,
737 ranges,
738 counts,
739 counts_size,
740 meta) {}
741
646 double LinearHistogram::GetBucketSize(Count current, size_t i) const { 742 double LinearHistogram::GetBucketSize(Count current, size_t i) const {
647 DCHECK_GT(ranges(i + 1), ranges(i)); 743 DCHECK_GT(ranges(i + 1), ranges(i));
648 // Adjacent buckets with different widths would have "surprisingly" many (few) 744 // Adjacent buckets with different widths would have "surprisingly" many (few)
649 // samples in a histogram if we didn't normalize this way. 745 // samples in a histogram if we didn't normalize this way.
650 double denominator = ranges(i + 1) - ranges(i); 746 double denominator = ranges(i + 1) - ranges(i);
651 return current/denominator; 747 return current/denominator;
652 } 748 }
653 749
654 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const { 750 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const {
655 int range = ranges(i); 751 int range = ranges(i);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
701 } 797 }
702 return histogram; 798 return histogram;
703 } 799 }
704 800
705 //------------------------------------------------------------------------------ 801 //------------------------------------------------------------------------------
706 // This section provides implementation for BooleanHistogram. 802 // This section provides implementation for BooleanHistogram.
707 //------------------------------------------------------------------------------ 803 //------------------------------------------------------------------------------
708 804
709 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name, 805 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name,
710 int32 flags) { 806 int32 flags) {
807 ImportPersistentHistograms();
808
711 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 809 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
712 if (!histogram) { 810 if (!histogram) {
713 // To avoid racy destruction at shutdown, the following will be leaked. 811 // To avoid racy destruction at shutdown, the following will be leaked.
714 BucketRanges* ranges = new BucketRanges(4); 812 BucketRanges* ranges = new BucketRanges(4);
715 LinearHistogram::InitializeBucketRanges(1, 2, ranges); 813 LinearHistogram::InitializeBucketRanges(1, 2, ranges);
716 const BucketRanges* registered_ranges = 814 const BucketRanges* registered_ranges =
717 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); 815 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
718 816
719 BooleanHistogram* tentative_histogram = 817 PersistentMemoryAllocator::Reference histogram_ref = 0;
720 new BooleanHistogram(name, registered_ranges); 818 HistogramBase* tentative_histogram = nullptr;
819 if (allocator_) {
820 flags |= kIsPersistent;
821 tentative_histogram = AllocatePersistentHistogram(
822 GetDefaultPersistentMemoryAllocator(),
823 BOOLEAN_HISTOGRAM,
824 name,
825 1, 2,
826 registered_ranges,
827 flags,
828 &histogram_ref);
829 }
830 if (!tentative_histogram) {
831 flags &= ~kIsPersistent;
832 tentative_histogram = new BooleanHistogram(name, registered_ranges);
833 }
721 834
722 tentative_histogram->SetFlags(flags); 835 tentative_histogram->SetFlags(flags);
723 histogram = 836 histogram =
724 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); 837 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
838
839 // Persistent histograms need some follow-up processing.
840 if (histogram_ref) {
841 // If the created persistent histogram is canonical then it needs to be
842 // marked as "iterable" in order to be found by other processes.
843 if (histogram == tentative_histogram)
844 GetDefaultPersistentMemoryAllocator()->MakeIterable(histogram_ref);
845 // If it's not the canonical one then a race condition must have caused
846 // two to be created. The allocator does not support releasing the
847 // acquired memory so just change the type to be empty.
848 else
849 GetDefaultPersistentMemoryAllocator()->SetType(histogram_ref, 0);
850 }
Alexei Svitkine (slow) 2015/12/04 18:27:36 The code from 817 to 850 is repeated in several pl
bcwhite 2015/12/07 23:27:19 Done.
725 } 851 }
726 852
727 DCHECK_EQ(BOOLEAN_HISTOGRAM, histogram->GetHistogramType()); 853 DCHECK_EQ(BOOLEAN_HISTOGRAM, histogram->GetHistogramType());
728 return histogram; 854 return histogram;
729 } 855 }
730 856
731 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32 flags) { 857 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32 flags) {
732 return FactoryGet(std::string(name), flags); 858 return FactoryGet(std::string(name), flags);
733 } 859 }
734 860
735 HistogramType BooleanHistogram::GetHistogramType() const { 861 HistogramType BooleanHistogram::GetHistogramType() const {
736 return BOOLEAN_HISTOGRAM; 862 return BOOLEAN_HISTOGRAM;
737 } 863 }
738 864
739 BooleanHistogram::BooleanHistogram(const std::string& name, 865 BooleanHistogram::BooleanHistogram(const std::string& name,
740 const BucketRanges* ranges) 866 const BucketRanges* ranges)
741 : LinearHistogram(name, 1, 2, ranges) {} 867 : LinearHistogram(name, 1, 2, ranges) {}
742 868
869 BooleanHistogram::BooleanHistogram(const std::string& name,
870 const BucketRanges* ranges,
871 HistogramBase::AtomicCount* counts,
872 HistogramSamples::Metadata* meta)
873 : LinearHistogram(name, 1, 2, ranges, counts, 2, meta) {}
874
743 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { 875 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) {
744 std::string histogram_name; 876 std::string histogram_name;
745 int flags; 877 int flags;
746 int declared_min; 878 int declared_min;
747 int declared_max; 879 int declared_max;
748 size_t bucket_count; 880 size_t bucket_count;
749 uint32 range_checksum; 881 uint32 range_checksum;
750 882
751 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, 883 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min,
752 &declared_max, &bucket_count, &range_checksum)) { 884 &declared_max, &bucket_count, &range_checksum)) {
(...skipping 11 matching lines...) Expand all
764 896
765 //------------------------------------------------------------------------------ 897 //------------------------------------------------------------------------------
766 // CustomHistogram: 898 // CustomHistogram:
767 //------------------------------------------------------------------------------ 899 //------------------------------------------------------------------------------
768 900
769 HistogramBase* CustomHistogram::FactoryGet( 901 HistogramBase* CustomHistogram::FactoryGet(
770 const std::string& name, 902 const std::string& name,
771 const std::vector<Sample>& custom_ranges, 903 const std::vector<Sample>& custom_ranges,
772 int32 flags) { 904 int32 flags) {
773 CHECK(ValidateCustomRanges(custom_ranges)); 905 CHECK(ValidateCustomRanges(custom_ranges));
906 ImportPersistentHistograms();
774 907
775 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 908 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
776 if (!histogram) { 909 if (!histogram) {
910 // To avoid racy destruction at shutdown, the following will be leaked.
777 BucketRanges* ranges = CreateBucketRangesFromCustomRanges(custom_ranges); 911 BucketRanges* ranges = CreateBucketRangesFromCustomRanges(custom_ranges);
778 const BucketRanges* registered_ranges = 912 const BucketRanges* registered_ranges =
779 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); 913 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
780 914
781 // To avoid racy destruction at shutdown, the following will be leaked. 915 PersistentMemoryAllocator::Reference histogram_ref = 0;
782 CustomHistogram* tentative_histogram = 916 HistogramBase* tentative_histogram = nullptr;
783 new CustomHistogram(name, registered_ranges); 917 if (allocator_) {
918 flags |= kIsPersistent;
919 tentative_histogram = AllocatePersistentHistogram(
920 GetDefaultPersistentMemoryAllocator(),
921 CUSTOM_HISTOGRAM,
922 name,
923 registered_ranges->range(1),
924 registered_ranges->range(registered_ranges->bucket_count() - 1),
925 registered_ranges,
926 flags,
927 &histogram_ref);
928 }
929 if (!tentative_histogram) {
930 flags &= ~kIsPersistent;
931 tentative_histogram = new CustomHistogram(name, registered_ranges);
932 }
784 933
785 tentative_histogram->SetFlags(flags); 934 tentative_histogram->SetFlags(flags);
786
787 histogram = 935 histogram =
788 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); 936 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
937
938 // Persistent histograms need some follow-up processing.
939 if (histogram_ref) {
940 // If the created persistent histogram is canonical then it needs to be
941 // marked as "iterable" in order to be found by other processes.
942 if (histogram == tentative_histogram)
943 GetDefaultPersistentMemoryAllocator()->MakeIterable(histogram_ref);
944 // If it's not the canonical one then a race condition must have caused
945 // two to be created. The allocator does not support releasing the
946 // acquired memory so just change the type to be empty.
947 else
948 GetDefaultPersistentMemoryAllocator()->SetType(histogram_ref, 0);
949 }
789 } 950 }
790 951
791 DCHECK_EQ(histogram->GetHistogramType(), CUSTOM_HISTOGRAM); 952 DCHECK_EQ(histogram->GetHistogramType(), CUSTOM_HISTOGRAM);
792 return histogram; 953 return histogram;
793 } 954 }
794 955
795 HistogramBase* CustomHistogram::FactoryGet( 956 HistogramBase* CustomHistogram::FactoryGet(
796 const char* name, 957 const char* name,
797 const std::vector<Sample>& custom_ranges, 958 const std::vector<Sample>& custom_ranges,
798 int32 flags) { 959 int32 flags) {
(...skipping 19 matching lines...) Expand all
818 return all_values; 979 return all_values;
819 } 980 }
820 981
821 CustomHistogram::CustomHistogram(const std::string& name, 982 CustomHistogram::CustomHistogram(const std::string& name,
822 const BucketRanges* ranges) 983 const BucketRanges* ranges)
823 : Histogram(name, 984 : Histogram(name,
824 ranges->range(1), 985 ranges->range(1),
825 ranges->range(ranges->bucket_count() - 1), 986 ranges->range(ranges->bucket_count() - 1),
826 ranges) {} 987 ranges) {}
827 988
989 CustomHistogram::CustomHistogram(const std::string& name,
990 const BucketRanges* ranges,
991 HistogramBase::AtomicCount* counts,
992 size_t counts_size,
993 HistogramSamples::Metadata* meta)
994 : Histogram(name,
995 ranges->range(1),
996 ranges->range(ranges->bucket_count() - 1),
997 ranges,
998 counts,
999 counts_size,
1000 meta) {}
1001
828 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { 1002 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const {
829 if (!Histogram::SerializeInfoImpl(pickle)) 1003 if (!Histogram::SerializeInfoImpl(pickle))
830 return false; 1004 return false;
831 1005
832 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't 1006 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't
833 // write them. 1007 // write them.
834 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { 1008 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) {
835 if (!pickle->WriteInt(bucket_ranges()->range(i))) 1009 if (!pickle->WriteInt(bucket_ranges()->range(i)))
836 return false; 1010 return false;
837 } 1011 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
899 1073
900 BucketRanges* bucket_ranges = new BucketRanges(ranges.size()); 1074 BucketRanges* bucket_ranges = new BucketRanges(ranges.size());
901 for (size_t i = 0; i < ranges.size(); i++) { 1075 for (size_t i = 0; i < ranges.size(); i++) {
902 bucket_ranges->set_range(i, ranges[i]); 1076 bucket_ranges->set_range(i, ranges[i]);
903 } 1077 }
904 bucket_ranges->ResetChecksum(); 1078 bucket_ranges->ResetChecksum();
905 return bucket_ranges; 1079 return bucket_ranges;
906 } 1080 }
907 1081
908 } // namespace base 1082 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698