Index: base/metrics/persistent_histogram_allocator.cc |
diff --git a/base/metrics/persistent_histogram_allocator.cc b/base/metrics/persistent_histogram_allocator.cc |
index 5f44b67311c57e9f9d08d8c4674a2860be8985bc..b2dae993ddf1170589ff8c7291f9d015c031bccd 100644 |
--- a/base/metrics/persistent_histogram_allocator.cc |
+++ b/base/metrics/persistent_histogram_allocator.cc |
@@ -340,24 +340,49 @@ std::unique_ptr<HistogramBase> PersistentHistogramAllocator::AllocateHistogram( |
return nullptr; |
} |
- size_t ranges_count = bucket_count + 1; |
- size_t ranges_bytes = ranges_count * sizeof(HistogramBase::Sample); |
+ // Since the StasticsRecorder keeps a global collection of BucketRanges |
+ // objects for re-use, it would be dangerous for one to hold a reference |
+ // from a persistent allocator that is not the global one (which is |
+ // permanent once set). If this stops being the case, this check can |
+ // become an "if" condition beside "!ranges_ref" below and before |
+ // set_persistent_reference() farther down. |
+ DCHECK_EQ(this, GlobalHistogramAllocator::Get()); |
+ |
+ // Re-use an existing BucketRanges persistent allocation if one is known; |
+ // otherwise, create one. |
+ PersistentMemoryAllocator::Reference ranges_ref = |
+ bucket_ranges->persistent_reference(); |
+ if (!ranges_ref) { |
+ size_t ranges_count = bucket_count + 1; |
+ size_t ranges_bytes = ranges_count * sizeof(HistogramBase::Sample); |
+ ranges_ref = |
+ memory_allocator_->Allocate(ranges_bytes, kTypeIdRangesArray); |
+ if (ranges_ref) { |
+ HistogramBase::Sample* ranges_data = |
+ memory_allocator_->GetAsArray<HistogramBase::Sample>( |
+ ranges_ref, kTypeIdRangesArray, ranges_count); |
+ if (ranges_data) { |
+ for (size_t i = 0; i < bucket_ranges->size(); ++i) |
+ ranges_data[i] = bucket_ranges->range(i); |
+ bucket_ranges->set_persistent_reference(ranges_ref); |
+ } else { |
+ // This should never happen but be tolerant if it does. |
+ NOTREACHED(); |
+ ranges_ref = PersistentMemoryAllocator::kReferenceNull; |
+ } |
+ } |
+ } else { |
+ DCHECK_EQ(kTypeIdRangesArray, memory_allocator_->GetType(ranges_ref)); |
+ } |
+ |
PersistentMemoryAllocator::Reference counts_ref = |
memory_allocator_->Allocate(counts_bytes, kTypeIdCountsArray); |
- PersistentMemoryAllocator::Reference ranges_ref = |
- memory_allocator_->Allocate(ranges_bytes, kTypeIdRangesArray); |
- HistogramBase::Sample* ranges_data = |
- memory_allocator_->GetAsArray<HistogramBase::Sample>( |
- ranges_ref, kTypeIdRangesArray, ranges_count); |
// Only continue here if all allocations were successful. If they weren't, |
// there is no way to free the space but that's not really a problem since |
// the allocations only fail because the space is full or corrupt and so |
// any future attempts will also fail. |
- if (counts_ref && ranges_data && histogram_data) { |
- for (size_t i = 0; i < bucket_ranges->size(); ++i) |
- ranges_data[i] = bucket_ranges->range(i); |
- |
+ if (counts_ref && ranges_ref && histogram_data) { |
histogram_data->minimum = minimum; |
histogram_data->maximum = maximum; |
// |bucket_count| must fit within 32-bits or the allocation of the counts |