Chromium Code Reviews| Index: base/metrics/histogram.cc |
| diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc |
| index 5e24e005fabb23560870e6c8914859d263553ef4..d23472258e9073b480661842f9e31bcb0b351ec1 100644 |
| --- a/base/metrics/histogram.cc |
| +++ b/base/metrics/histogram.cc |
| @@ -17,6 +17,7 @@ |
| #include "base/compiler_specific.h" |
| #include "base/debug/alias.h" |
| #include "base/logging.h" |
| +#include "base/memory/persistent_memory_allocator.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "base/metrics/metrics_hashes.h" |
| #include "base/metrics/sample_vector.h" |
| @@ -91,6 +92,7 @@ HistogramBase* Histogram::FactoryGet(const std::string& name, |
| bool valid_arguments = |
| InspectConstructionArguments(name, &minimum, &maximum, &bucket_count); |
| DCHECK(valid_arguments); |
| + ImportPersistentHistograms(); |
| HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); |
| if (!histogram) { |
| @@ -100,12 +102,42 @@ HistogramBase* Histogram::FactoryGet(const std::string& name, |
| const BucketRanges* registered_ranges = |
| StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); |
| - Histogram* tentative_histogram = |
| - new Histogram(name, minimum, maximum, registered_ranges); |
| + PersistentMemoryAllocator::Reference histogram_ref = 0; |
| + HistogramBase* tentative_histogram = nullptr; |
| + if (allocator_) { |
| + flags |= kIsPersistent; |
| + tentative_histogram = AllocatePersistentHistogram( |
| + GetDefaultPersistentMemoryAllocator(), |
| + HISTOGRAM, |
| + name, |
| + minimum, |
| + maximum, |
| + registered_ranges, |
| + flags, |
| + &histogram_ref); |
| + } |
| + if (!tentative_histogram) { |
| + flags &= ~kIsPersistent; |
| + tentative_histogram = new Histogram( |
| + name, minimum, maximum, registered_ranges); |
| + } |
| tentative_histogram->SetFlags(flags); |
| histogram = |
| StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
| + |
| + // Persistent histograms need some follow-up processing. |
| + if (histogram_ref) { |
| + // If the created persistent histogram is canonical then it needs to be |
| + // marked as "iterable" in order to be found by other processes. |
| + if (histogram == tentative_histogram) |
| + GetDefaultPersistentMemoryAllocator()->MakeIterable(histogram_ref); |
| + // If it's not the canonical one then a race condition must have caused |
| + // two to be created. The allocator does not support releasing the |
| + // acquired memory so just change the type to be empty. |
| + else |
| + GetDefaultPersistentMemoryAllocator()->SetType(histogram_ref, 0); |
| + } |
| } |
| DCHECK_EQ(HISTOGRAM, histogram->GetHistogramType()); |
| @@ -344,6 +376,22 @@ Histogram::Histogram(const std::string& name, |
| samples_.reset(new SampleVector(HashMetricName(name), ranges)); |
| } |
| +Histogram::Histogram(const std::string& name, |
| + Sample minimum, |
| + Sample maximum, |
| + const BucketRanges* ranges, |
| + HistogramBase::AtomicCount* counts, |
| + size_t counts_size, |
| + HistogramSamples::Metadata* meta) |
| + : HistogramBase(name), |
| + bucket_ranges_(ranges), |
| + declared_min_(minimum), |
| + declared_max_(maximum) { |
| + if (ranges) |
| + samples_.reset(new SampleVector(HashMetricName(name), |
| + counts, counts_size, meta, ranges)); |
| +} |
| + |
| Histogram::~Histogram() { |
| } |
| @@ -399,7 +447,8 @@ HistogramBase* Histogram::DeserializeInfoImpl(PickleIterator* iter) { |
| scoped_ptr<SampleVector> Histogram::SnapshotSampleVector() const { |
| scoped_ptr<SampleVector> samples( |
| - new SampleVector(HashMetricName(histogram_name()), bucket_ranges())); |
| + new SampleVector(HashMetricName(histogram_name()), |
| + bucket_ranges())); |
| samples->Add(*samples_); |
| return samples; |
| } |
| @@ -593,6 +642,7 @@ HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( |
| bool valid_arguments = Histogram::InspectConstructionArguments( |
| name, &minimum, &maximum, &bucket_count); |
| DCHECK(valid_arguments); |
| + ImportPersistentHistograms(); |
| HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); |
| if (!histogram) { |
| @@ -602,8 +652,26 @@ HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( |
| const BucketRanges* registered_ranges = |
| StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); |
| - LinearHistogram* tentative_histogram = |
| - new LinearHistogram(name, minimum, maximum, registered_ranges); |
| + PersistentMemoryAllocator::Reference histogram_ref = 0; |
| + LinearHistogram* tentative_histogram = nullptr; |
| + if (allocator_) { |
| + flags |= kIsPersistent; |
| + tentative_histogram = static_cast<LinearHistogram*>( |
| + AllocatePersistentHistogram( |
| + GetDefaultPersistentMemoryAllocator(), |
| + LINEAR_HISTOGRAM, |
| + name, |
| + minimum, |
| + maximum, |
| + registered_ranges, |
| + flags, |
| + &histogram_ref)); |
| + } |
| + if (!tentative_histogram) { |
| + flags &= ~kIsPersistent; |
| + tentative_histogram = new LinearHistogram( |
| + name, minimum, maximum, registered_ranges); |
| + } |
| // Set range descriptions. |
| if (descriptions) { |
| @@ -616,6 +684,19 @@ HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( |
| tentative_histogram->SetFlags(flags); |
| histogram = |
| StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
| + |
| + // Persistent histograms need some follow-up processing. |
| + if (histogram_ref) { |
| + // If the created persistent histogram is canonical then it needs to be |
| + // marked as "iterable" in order to be found by other processes. |
| + if (histogram == tentative_histogram) |
| + GetDefaultPersistentMemoryAllocator()->MakeIterable(histogram_ref); |
| + // If it's not the canonical one then a race condition must have caused |
| + // two to be created. The allocator does not support releasing the |
| + // acquired memory so just change the type to be empty. |
| + else |
| + GetDefaultPersistentMemoryAllocator()->SetType(histogram_ref, 0); |
| + } |
| } |
| DCHECK_EQ(LINEAR_HISTOGRAM, histogram->GetHistogramType()); |
| @@ -643,6 +724,21 @@ LinearHistogram::LinearHistogram(const std::string& name, |
| : Histogram(name, minimum, maximum, ranges) { |
| } |
| +LinearHistogram::LinearHistogram(const std::string& name, |
| + Sample minimum, |
| + Sample maximum, |
| + const BucketRanges* ranges, |
| + HistogramBase::AtomicCount* counts, |
| + size_t counts_size, |
| + HistogramSamples::Metadata* meta) |
| + : Histogram(name, |
| + minimum, |
| + maximum, |
| + ranges, |
| + counts, |
| + counts_size, |
| + meta) {} |
| + |
| double LinearHistogram::GetBucketSize(Count current, size_t i) const { |
| DCHECK_GT(ranges(i + 1), ranges(i)); |
| // Adjacent buckets with different widths would have "surprisingly" many (few) |
| @@ -708,6 +804,8 @@ HistogramBase* LinearHistogram::DeserializeInfoImpl(PickleIterator* iter) { |
| HistogramBase* BooleanHistogram::FactoryGet(const std::string& name, |
| int32 flags) { |
| + ImportPersistentHistograms(); |
| + |
| HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); |
| if (!histogram) { |
| // To avoid racy destruction at shutdown, the following will be leaked. |
| @@ -716,12 +814,40 @@ HistogramBase* BooleanHistogram::FactoryGet(const std::string& name, |
| const BucketRanges* registered_ranges = |
| StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); |
| - BooleanHistogram* tentative_histogram = |
| - new BooleanHistogram(name, registered_ranges); |
| + PersistentMemoryAllocator::Reference histogram_ref = 0; |
| + HistogramBase* tentative_histogram = nullptr; |
| + if (allocator_) { |
| + flags |= kIsPersistent; |
| + tentative_histogram = AllocatePersistentHistogram( |
| + GetDefaultPersistentMemoryAllocator(), |
| + BOOLEAN_HISTOGRAM, |
| + name, |
| + 1, 2, |
| + registered_ranges, |
| + flags, |
| + &histogram_ref); |
| + } |
| + if (!tentative_histogram) { |
| + flags &= ~kIsPersistent; |
| + tentative_histogram = new BooleanHistogram(name, registered_ranges); |
| + } |
| tentative_histogram->SetFlags(flags); |
| histogram = |
| StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
| + |
| + // Persistent histograms need some follow-up processing. |
| + if (histogram_ref) { |
| + // If the created persistent histogram is canonical then it needs to be |
| + // marked as "iterable" in order to be found by other processes. |
| + if (histogram == tentative_histogram) |
| + GetDefaultPersistentMemoryAllocator()->MakeIterable(histogram_ref); |
| + // If it's not the canonical one then a race condition must have caused |
| + // two to be created. The allocator does not support releasing the |
| + // acquired memory so just change the type to be empty. |
| + else |
| + GetDefaultPersistentMemoryAllocator()->SetType(histogram_ref, 0); |
| + } |
|
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.
|
| } |
| DCHECK_EQ(BOOLEAN_HISTOGRAM, histogram->GetHistogramType()); |
| @@ -740,6 +866,12 @@ BooleanHistogram::BooleanHistogram(const std::string& name, |
| const BucketRanges* ranges) |
| : LinearHistogram(name, 1, 2, ranges) {} |
| +BooleanHistogram::BooleanHistogram(const std::string& name, |
| + const BucketRanges* ranges, |
| + HistogramBase::AtomicCount* counts, |
| + HistogramSamples::Metadata* meta) |
| + : LinearHistogram(name, 1, 2, ranges, counts, 2, meta) {} |
| + |
| HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { |
| std::string histogram_name; |
| int flags; |
| @@ -771,21 +903,50 @@ HistogramBase* CustomHistogram::FactoryGet( |
| const std::vector<Sample>& custom_ranges, |
| int32 flags) { |
| CHECK(ValidateCustomRanges(custom_ranges)); |
| + ImportPersistentHistograms(); |
| HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); |
| if (!histogram) { |
| + // To avoid racy destruction at shutdown, the following will be leaked. |
| BucketRanges* ranges = CreateBucketRangesFromCustomRanges(custom_ranges); |
| const BucketRanges* registered_ranges = |
| StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); |
| - // To avoid racy destruction at shutdown, the following will be leaked. |
| - CustomHistogram* tentative_histogram = |
| - new CustomHistogram(name, registered_ranges); |
| + PersistentMemoryAllocator::Reference histogram_ref = 0; |
| + HistogramBase* tentative_histogram = nullptr; |
| + if (allocator_) { |
| + flags |= kIsPersistent; |
| + tentative_histogram = AllocatePersistentHistogram( |
| + GetDefaultPersistentMemoryAllocator(), |
| + CUSTOM_HISTOGRAM, |
| + name, |
| + registered_ranges->range(1), |
| + registered_ranges->range(registered_ranges->bucket_count() - 1), |
| + registered_ranges, |
| + flags, |
| + &histogram_ref); |
| + } |
| + if (!tentative_histogram) { |
| + flags &= ~kIsPersistent; |
| + tentative_histogram = new CustomHistogram(name, registered_ranges); |
| + } |
| tentative_histogram->SetFlags(flags); |
| - |
| histogram = |
| StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
| + |
| + // Persistent histograms need some follow-up processing. |
| + if (histogram_ref) { |
| + // If the created persistent histogram is canonical then it needs to be |
| + // marked as "iterable" in order to be found by other processes. |
| + if (histogram == tentative_histogram) |
| + GetDefaultPersistentMemoryAllocator()->MakeIterable(histogram_ref); |
| + // If it's not the canonical one then a race condition must have caused |
| + // two to be created. The allocator does not support releasing the |
| + // acquired memory so just change the type to be empty. |
| + else |
| + GetDefaultPersistentMemoryAllocator()->SetType(histogram_ref, 0); |
| + } |
| } |
| DCHECK_EQ(histogram->GetHistogramType(), CUSTOM_HISTOGRAM); |
| @@ -825,6 +986,19 @@ CustomHistogram::CustomHistogram(const std::string& name, |
| ranges->range(ranges->bucket_count() - 1), |
| ranges) {} |
| +CustomHistogram::CustomHistogram(const std::string& name, |
| + const BucketRanges* ranges, |
| + HistogramBase::AtomicCount* counts, |
| + size_t counts_size, |
| + HistogramSamples::Metadata* meta) |
| + : Histogram(name, |
| + ranges->range(1), |
| + ranges->range(ranges->bucket_count() - 1), |
| + ranges, |
| + counts, |
| + counts_size, |
| + meta) {} |
| + |
| bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { |
| if (!Histogram::SerializeInfoImpl(pickle)) |
| return false; |