summaryrefslogtreecommitdiff
path: root/chromium/base/metrics/statistics_recorder.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-05-09 14:22:11 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2016-05-09 15:11:45 +0000
commit2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c (patch)
treee75f511546c5fd1a173e87c1f9fb11d7ac8d1af3 /chromium/base/metrics/statistics_recorder.cc
parenta4f3d46271c57e8155ba912df46a05559d14726e (diff)
downloadqtwebengine-chromium-2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c.tar.gz
BASELINE: Update Chromium to 51.0.2704.41
Also adds in all smaller components by reversing logic for exclusion. Change-Id: Ibf90b506e7da088ea2f65dcf23f2b0992c504422 Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
Diffstat (limited to 'chromium/base/metrics/statistics_recorder.cc')
-rw-r--r--chromium/base/metrics/statistics_recorder.cc202
1 files changed, 162 insertions, 40 deletions
diff --git a/chromium/base/metrics/statistics_recorder.cc b/chromium/base/metrics/statistics_recorder.cc
index b18efad280a..07e81b0f1b6 100644
--- a/chromium/base/metrics/statistics_recorder.cc
+++ b/chromium/base/metrics/statistics_recorder.cc
@@ -4,13 +4,15 @@
#include "base/metrics/statistics_recorder.h"
+#include <memory>
+
#include "base/at_exit.h"
#include "base/debug/leak_annotations.h"
#include "base/json/string_escape.h"
#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
#include "base/metrics/metrics_hashes.h"
+#include "base/metrics/persistent_histogram_allocator.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h"
@@ -31,6 +33,55 @@ bool HistogramNameLesser(const base::HistogramBase* a,
namespace base {
+StatisticsRecorder::HistogramIterator::HistogramIterator(
+ const HistogramMap::iterator& iter, bool include_persistent)
+ : iter_(iter),
+ include_persistent_(include_persistent) {
+}
+
+StatisticsRecorder::HistogramIterator::HistogramIterator(
+ const HistogramIterator& rhs)
+ : iter_(rhs.iter_),
+ include_persistent_(rhs.include_persistent_) {
+}
+
+StatisticsRecorder::HistogramIterator::~HistogramIterator() {}
+
+StatisticsRecorder::HistogramIterator&
+StatisticsRecorder::HistogramIterator::operator++() {
+ const HistogramMap::iterator histograms_end = histograms_->end();
+ if (iter_ == histograms_end || lock_ == NULL)
+ return *this;
+
+ base::AutoLock auto_lock(*lock_);
+
+ for (;;) {
+ ++iter_;
+ if (iter_ == histograms_end)
+ break;
+ if (!include_persistent_ && (iter_->second->flags() &
+ HistogramBase::kIsPersistent)) {
+ continue;
+ }
+ break;
+ }
+
+ return *this;
+}
+
+StatisticsRecorder::~StatisticsRecorder() {
+ DCHECK(lock_);
+ DCHECK(histograms_);
+ DCHECK(ranges_);
+
+ // Clean out what this object created and then restore what existed before.
+ Reset();
+ base::AutoLock auto_lock(*lock_);
+ histograms_ = existing_histograms_.release();
+ callbacks_ = existing_callbacks_.release();
+ ranges_ = existing_ranges_.release();
+}
+
// static
void StatisticsRecorder::Initialize() {
// Ensure that an instance of the StatisticsRecorder object is created.
@@ -66,10 +117,11 @@ HistogramBase* StatisticsRecorder::RegisterOrDeleteDuplicate(
histogram_to_return = histogram;
} else {
const std::string& name = histogram->histogram_name();
- uint64_t name_hash = histogram->name_hash();
- HistogramMap::iterator it = histograms_->find(name_hash);
+ HistogramMap::iterator it = histograms_->find(name);
if (histograms_->end() == it) {
- (*histograms_)[name_hash] = histogram;
+ // The StringKey references the name within |histogram| rather than
+ // making a copy.
+ (*histograms_)[name] = histogram;
ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322
// If there are callbacks for this histogram, we set the kCallbackExists
// flag.
@@ -101,7 +153,7 @@ HistogramBase* StatisticsRecorder::RegisterOrDeleteDuplicate(
const BucketRanges* StatisticsRecorder::RegisterOrDeleteDuplicateRanges(
const BucketRanges* ranges) {
DCHECK(ranges->HasValidChecksum());
- scoped_ptr<const BucketRanges> ranges_deleter;
+ std::unique_ptr<const BucketRanges> ranges_deleter;
if (lock_ == NULL) {
ANNOTATE_LEAKING_OBJECT_PTR(ranges);
@@ -213,7 +265,6 @@ void StatisticsRecorder::GetHistograms(Histograms* output) {
return;
for (const auto& entry : *histograms_) {
- DCHECK_EQ(entry.first, entry.second->name_hash());
output->push_back(entry.second);
}
}
@@ -235,21 +286,70 @@ void StatisticsRecorder::GetBucketRanges(
}
// static
-HistogramBase* StatisticsRecorder::FindHistogram(const std::string& name) {
+HistogramBase* StatisticsRecorder::FindHistogram(base::StringPiece name) {
if (lock_ == NULL)
return NULL;
+
+ // Import histograms from known persistent storage. Histograms could have
+ // been added by other processes and they must be fetched and recognized
+ // locally. If the persistent memory segment is not shared between processes,
+ // this call does nothing.
+ // This must be called *before* the lock is acquired below because it will
+ // call back into this object to register histograms. Those called methods
+ // will acquire the lock at that time.
+ GlobalHistogramAllocator* allocator = GlobalHistogramAllocator::Get();
+ if (allocator)
+ allocator->ImportHistogramsToStatisticsRecorder();
+
base::AutoLock auto_lock(*lock_);
if (histograms_ == NULL)
return NULL;
- HistogramMap::iterator it = histograms_->find(HashMetricName(name));
+ HistogramMap::iterator it = histograms_->find(name);
if (histograms_->end() == it)
return NULL;
- DCHECK_EQ(name, it->second->histogram_name()) << "hash collision";
return it->second;
}
// static
+StatisticsRecorder::HistogramIterator StatisticsRecorder::begin(
+ bool include_persistent) {
+ DCHECK(histograms_);
+
+ HistogramMap::iterator iter_begin;
+ {
+ base::AutoLock auto_lock(*lock_);
+ iter_begin = histograms_->begin();
+ }
+ return HistogramIterator(iter_begin, include_persistent);
+}
+
+// static
+StatisticsRecorder::HistogramIterator StatisticsRecorder::end() {
+ HistogramMap::iterator iter_end;
+ {
+ base::AutoLock auto_lock(*lock_);
+ iter_end = histograms_->end();
+ }
+ return HistogramIterator(iter_end, true);
+}
+
+// static
+void StatisticsRecorder::GetSnapshot(const std::string& query,
+ Histograms* snapshot) {
+ if (lock_ == NULL)
+ return;
+ base::AutoLock auto_lock(*lock_);
+ if (histograms_ == NULL)
+ return;
+
+ for (const auto& entry : *histograms_) {
+ if (entry.second->histogram_name().find(query) != std::string::npos)
+ snapshot->push_back(entry.second);
+ }
+}
+
+// static
bool StatisticsRecorder::SetCallback(
const std::string& name,
const StatisticsRecorder::OnSampleCallback& cb) {
@@ -264,11 +364,9 @@ bool StatisticsRecorder::SetCallback(
return false;
callbacks_->insert(std::make_pair(name, cb));
- HistogramMap::iterator it = histograms_->find(HashMetricName(name));
- if (it != histograms_->end()) {
- DCHECK_EQ(name, it->second->histogram_name()) << "hash collision";
+ auto it = histograms_->find(name);
+ if (it != histograms_->end())
it->second->SetFlags(HistogramBase::kCallbackExists);
- }
return true;
}
@@ -284,11 +382,9 @@ void StatisticsRecorder::ClearCallback(const std::string& name) {
callbacks_->erase(name);
// We also clear the flag from the histogram (if it exists).
- HistogramMap::iterator it = histograms_->find(HashMetricName(name));
- if (it != histograms_->end()) {
- DCHECK_EQ(name, it->second->histogram_name()) << "hash collision";
+ auto it = histograms_->find(name);
+ if (it != histograms_->end())
it->second->ClearFlags(HistogramBase::kCallbackExists);
- }
}
// static
@@ -305,26 +401,44 @@ StatisticsRecorder::OnSampleCallback StatisticsRecorder::FindCallback(
: OnSampleCallback();
}
-// private static
-void StatisticsRecorder::GetSnapshot(const std::string& query,
- Histograms* snapshot) {
- if (lock_ == NULL)
- return;
+// static
+size_t StatisticsRecorder::GetHistogramCount() {
+ if (!lock_)
+ return 0;
+
base::AutoLock auto_lock(*lock_);
- if (histograms_ == NULL)
+ if (!histograms_)
+ return 0;
+ return histograms_->size();
+}
+
+// static
+void StatisticsRecorder::ForgetHistogramForTesting(base::StringPiece name) {
+ if (histograms_)
+ histograms_->erase(name);
+}
+
+// static
+void StatisticsRecorder::UninitializeForTesting() {
+ // Stop now if it's never been initialized.
+ if (lock_ == NULL || histograms_ == NULL)
return;
- for (const auto& entry : *histograms_) {
- if (entry.second->histogram_name().find(query) != std::string::npos)
- snapshot->push_back(entry.second);
- }
+ // Get the global instance and destruct it. It's held in static memory so
+ // can't "delete" it; call the destructor explicitly.
+ DCHECK(g_statistics_recorder_.private_instance_);
+ g_statistics_recorder_.Get().~StatisticsRecorder();
+
+ // Now the ugly part. There's no official way to release a LazyInstance once
+ // created so it's necessary to clear out an internal variable which
+ // shouldn't be publicly visible but is for initialization reasons.
+ g_statistics_recorder_.private_instance_ = 0;
}
// This singleton instance should be started during the single threaded portion
// of main(), and hence it is not thread safe. It initializes globals to
// provide support for all future calls.
StatisticsRecorder::StatisticsRecorder() {
- DCHECK(!histograms_);
if (lock_ == NULL) {
// This will leak on purpose. It's the only way to make sure we won't race
// against the static uninitialization of the module while one of our
@@ -334,7 +448,13 @@ StatisticsRecorder::StatisticsRecorder() {
// during static initialization and released only on process termination.
lock_ = new base::Lock;
}
+
base::AutoLock auto_lock(*lock_);
+
+ existing_histograms_.reset(histograms_);
+ existing_callbacks_.reset(callbacks_);
+ existing_ranges_.reset(ranges_);
+
histograms_ = new HistogramMap;
callbacks_ = new CallbackMap;
ranges_ = new RangesMap;
@@ -344,19 +464,14 @@ StatisticsRecorder::StatisticsRecorder() {
}
// static
-void StatisticsRecorder::DumpHistogramsToVlog(void* instance) {
- std::string output;
- StatisticsRecorder::WriteGraph(std::string(), &output);
- VLOG(1) << output;
-}
-
-StatisticsRecorder::~StatisticsRecorder() {
- DCHECK(histograms_ && ranges_ && lock_);
+void StatisticsRecorder::Reset() {
+ // If there's no lock then there is nothing to reset.
+ if (!lock_)
+ return;
- // Clean up.
- scoped_ptr<HistogramMap> histograms_deleter;
- scoped_ptr<CallbackMap> callbacks_deleter;
- scoped_ptr<RangesMap> ranges_deleter;
+ std::unique_ptr<HistogramMap> histograms_deleter;
+ std::unique_ptr<CallbackMap> callbacks_deleter;
+ std::unique_ptr<RangesMap> ranges_deleter;
// We don't delete lock_ on purpose to avoid having to properly protect
// against it going away after we checked for NULL in the static methods.
{
@@ -371,6 +486,13 @@ StatisticsRecorder::~StatisticsRecorder() {
// We are going to leak the histograms and the ranges.
}
+// static
+void StatisticsRecorder::DumpHistogramsToVlog(void* instance) {
+ std::string output;
+ StatisticsRecorder::WriteGraph(std::string(), &output);
+ VLOG(1) << output;
+}
+
// static
StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL;