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; |