| Index: base/metrics/sparse_histogram.cc
|
| diff --git a/base/metrics/sparse_histogram.cc b/base/metrics/sparse_histogram.cc
|
| index 5653456a29fb552470871f8611cb6337ec65bc50..978514bbce03c46b74606faea4e52b823f082ecd 100644
|
| --- a/base/metrics/sparse_histogram.cc
|
| +++ b/base/metrics/sparse_histogram.cc
|
| @@ -6,6 +6,7 @@
|
|
|
| #include <utility>
|
|
|
| +#include "base/metrics/histogram_persistence.h"
|
| #include "base/metrics/metrics_hashes.h"
|
| #include "base/metrics/sample_map.h"
|
| #include "base/metrics/statistics_recorder.h"
|
| @@ -21,23 +22,73 @@ typedef HistogramBase::Sample Sample;
|
| // static
|
| HistogramBase* SparseHistogram::FactoryGet(const std::string& name,
|
| int32_t flags) {
|
| - HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
|
| + // Import histograms from known persistent storage. Histograms could have
|
| + // been added by other processes and they must be fetched and recognized
|
| + // locally in order to be found by FindHistograms() below. If the persistent
|
| + // memory segment is not shared between processes, this call does nothing.
|
| + ImportPersistentHistograms();
|
|
|
| + HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
|
| if (!histogram) {
|
| - // To avoid racy destruction at shutdown, the following will be leaked.
|
| - HistogramBase* tentative_histogram = new SparseHistogram(name);
|
| + // Try to create the histogram using a "persistent" allocator. As of
|
| + // 2016-02-25, the availability of such is controlled by a base::Feature
|
| + // that is off by default. If the allocator doesn't exist or if
|
| + // allocating from it fails, code below will allocate the histogram from
|
| + // the process heap.
|
| + PersistentMemoryAllocator::Reference histogram_ref = 0;
|
| + HistogramBase* tentative_histogram = nullptr;
|
| + PersistentMemoryAllocator* allocator =
|
| + GetPersistentHistogramMemoryAllocator();
|
| + if (allocator) {
|
| + flags |= HistogramBase::kIsPersistent;
|
| + tentative_histogram = AllocatePersistentHistogram(
|
| + allocator,
|
| + SPARSE_HISTOGRAM,
|
| + name,
|
| + 0,
|
| + 0,
|
| + nullptr,
|
| + flags,
|
| + &histogram_ref);
|
| + }
|
| +
|
| + // Handle the case where no persistent allocator is present or the
|
| + // persistent allocation fails (perhaps because it is full).
|
| + if (!tentative_histogram) {
|
| + DCHECK(!histogram_ref); // Should never have been set.
|
| + DCHECK(!allocator); // Shouldn't have failed.
|
| + flags &= ~HistogramBase::kIsPersistent;
|
| + tentative_histogram = new SparseHistogram(name);
|
| + }
|
| +
|
| tentative_histogram->SetFlags(flags);
|
| histogram =
|
| StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
|
| +
|
| + // Persistent histograms need some follow-up processing.
|
| + if (histogram_ref) {
|
| + FinalizePersistentHistogram(histogram_ref,
|
| + histogram == tentative_histogram);
|
| + }
|
| }
|
| +
|
| DCHECK_EQ(SPARSE_HISTOGRAM, histogram->GetHistogramType());
|
| return histogram;
|
| }
|
|
|
| +// static
|
| +HistogramBase* SparseHistogram::PersistentGet(
|
| + PersistentMemoryAllocator* allocator,
|
| + const std::string& name,
|
| + HistogramSamples::Metadata* meta,
|
| + HistogramSamples::Metadata* logged_meta) {
|
| + return new SparseHistogram(allocator, name, meta, logged_meta);
|
| +}
|
| +
|
| SparseHistogram::~SparseHistogram() {}
|
|
|
| uint64_t SparseHistogram::name_hash() const {
|
| - return samples_.id();
|
| + return samples_->id();
|
| }
|
|
|
| HistogramType SparseHistogram::GetHistogramType() const {
|
| @@ -63,7 +114,7 @@ void SparseHistogram::AddCount(Sample value, int count) {
|
| }
|
| {
|
| base::AutoLock auto_lock(lock_);
|
| - samples_.Accumulate(value, count);
|
| + samples_->Accumulate(value, count);
|
| }
|
|
|
| FindAndRunCallback(value);
|
| @@ -73,29 +124,29 @@ scoped_ptr<HistogramSamples> SparseHistogram::SnapshotSamples() const {
|
| scoped_ptr<SampleMap> snapshot(new SampleMap(name_hash()));
|
|
|
| base::AutoLock auto_lock(lock_);
|
| - snapshot->Add(samples_);
|
| + snapshot->Add(*samples_);
|
| return std::move(snapshot);
|
| }
|
|
|
| scoped_ptr<HistogramSamples> SparseHistogram::SnapshotDelta() {
|
| scoped_ptr<SampleMap> snapshot(new SampleMap(name_hash()));
|
| base::AutoLock auto_lock(lock_);
|
| - snapshot->Add(samples_);
|
| + snapshot->Add(*samples_);
|
|
|
| // Subtract what was previously logged and update that information.
|
| - snapshot->Subtract(logged_samples_);
|
| - logged_samples_.Add(*snapshot);
|
| + snapshot->Subtract(*logged_samples_);
|
| + logged_samples_->Add(*snapshot);
|
| return std::move(snapshot);
|
| }
|
|
|
| void SparseHistogram::AddSamples(const HistogramSamples& samples) {
|
| base::AutoLock auto_lock(lock_);
|
| - samples_.Add(samples);
|
| + samples_->Add(samples);
|
| }
|
|
|
| bool SparseHistogram::AddSamplesFromPickle(PickleIterator* iter) {
|
| base::AutoLock auto_lock(lock_);
|
| - return samples_.AddFromPickle(iter);
|
| + return samples_->AddFromPickle(iter);
|
| }
|
|
|
| void SparseHistogram::WriteHTMLGraph(std::string* output) const {
|
| @@ -114,7 +165,19 @@ bool SparseHistogram::SerializeInfoImpl(Pickle* pickle) const {
|
|
|
| SparseHistogram::SparseHistogram(const std::string& name)
|
| : HistogramBase(name),
|
| - samples_(HashMetricName(name)) {}
|
| + samples_(new SampleMap(HashMetricName(name))),
|
| + logged_samples_(new SampleMap(samples_->id())) {}
|
| +
|
| +SparseHistogram::SparseHistogram(PersistentMemoryAllocator* allocator,
|
| + const std::string& name,
|
| + HistogramSamples::Metadata* meta,
|
| + HistogramSamples::Metadata* logged_meta)
|
| + : HistogramBase(name),
|
| + samples_(new PersistentSampleMap(HashMetricName(name), allocator, meta)),
|
| + // The ID must be different so as to not confuse sample records.
|
| + logged_samples_(
|
| + new PersistentSampleMap(samples_->id() + 1, allocator, logged_meta)) {
|
| +}
|
|
|
| HistogramBase* SparseHistogram::DeserializeInfoImpl(PickleIterator* iter) {
|
| std::string histogram_name;
|
|
|