diff options
author | rtenneti@google.com <rtenneti@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-12 18:19:45 +0000 |
---|---|---|
committer | rtenneti@google.com <rtenneti@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-12 18:19:45 +0000 |
commit | 83ab4a28583780761ec6e3cddd4418c2c16c049c (patch) | |
tree | 7c0ae2b3048546848331bb46ec14f493954eb8fc /base | |
parent | 447a5b6333539c309e015ee8f98ff6d9e131fa85 (diff) | |
download | chromium_src-83ab4a28583780761ec6e3cddd4418c2c16c049c.zip chromium_src-83ab4a28583780761ec6e3cddd4418c2c16c049c.tar.gz chromium_src-83ab4a28583780761ec6e3cddd4418c2c16c049c.tar.bz2 |
Histograms - Support histograms for Plugins, GPU
and all child processes. Renderer processes also
use this new method to send histograms to browser.
This code is similar to the code that gets profiler
data from all processes.
R=jar@chromium.org,jam@chromium.org
TEST=browser unit tests, interactive UI tests
BUG=114013
Review URL: https://chromiumcodereview.appspot.com/10454086
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@146394 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/base.gypi | 3 | ||||
-rw-r--r-- | base/metrics/histogram_flattener.h | 40 | ||||
-rw-r--r-- | base/metrics/histogram_snapshot_manager.cc | 104 | ||||
-rw-r--r-- | base/metrics/histogram_snapshot_manager.h | 60 |
4 files changed, 207 insertions, 0 deletions
diff --git a/base/base.gypi b/base/base.gypi index b605ae5..cfc904c 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -235,6 +235,9 @@ 'message_pump_win.h', 'metrics/histogram.cc', 'metrics/histogram.h', + 'metrics/histogram_flattener.h', + 'metrics/histogram_snapshot_manager.cc', + 'metrics/histogram_snapshot_manager.h', 'metrics/stats_counters.cc', 'metrics/stats_counters.h', 'metrics/stats_table.cc', diff --git a/base/metrics/histogram_flattener.h b/base/metrics/histogram_flattener.h new file mode 100644 index 0000000..edb1511 --- /dev/null +++ b/base/metrics/histogram_flattener.h @@ -0,0 +1,40 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_METRICS_HISTOGRAM_FLATTENER_H_ +#define BASE_METRICS_HISTOGRAM_FLATTENER_H_ + +#include <map> +#include <string> + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/metrics/histogram.h" + +namespace base { + +// HistogramFlattener is an interface for the logistics of gathering up +// available histograms for recording. The implementors handle the exact lower +// level recording mechanism, or error report mechanism. +class BASE_EXPORT HistogramFlattener { + public: + virtual void RecordDelta(const base::Histogram& histogram, + const base::Histogram::SampleSet& snapshot) = 0; + + // Record various errors found during attempts to record histograms. + virtual void InconsistencyDetected(int problem) = 0; + virtual void UniqueInconsistencyDetected(int problem) = 0; + virtual void SnapshotProblemResolved(int amount) = 0; + + protected: + HistogramFlattener() {} + virtual ~HistogramFlattener() {} + + private: + DISALLOW_COPY_AND_ASSIGN(HistogramFlattener); +}; + +} // namespace base + +#endif // BASE_METRICS_HISTOGRAM_FLATTENER_H_ diff --git a/base/metrics/histogram_snapshot_manager.cc b/base/metrics/histogram_snapshot_manager.cc new file mode 100644 index 0000000..b325f73 --- /dev/null +++ b/base/metrics/histogram_snapshot_manager.cc @@ -0,0 +1,104 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/metrics/histogram_snapshot_manager.h" + +using base::Histogram; +using base::StatisticsRecorder; + +namespace base { + +HistogramSnapshotManager::HistogramSnapshotManager( + HistogramFlattener* histogram_flattener) + : histogram_flattener_(histogram_flattener) { + DCHECK(histogram_flattener_); +} + +HistogramSnapshotManager::~HistogramSnapshotManager() {} + +void HistogramSnapshotManager::PrepareDeltas(Histogram::Flags flag_to_set, + bool record_only_uma) { + StatisticsRecorder::Histograms histograms; + StatisticsRecorder::GetHistograms(&histograms); + for (StatisticsRecorder::Histograms::const_iterator it = histograms.begin(); + histograms.end() != it; + ++it) { + (*it)->SetFlags(flag_to_set); + if (record_only_uma && + 0 == ((*it)->flags() & Histogram::kUmaTargetedHistogramFlag)) + continue; + PrepareDelta(**it); + } +} + +void HistogramSnapshotManager::PrepareDelta(const Histogram& histogram) { + DCHECK(histogram_flattener_); + + // Get up-to-date snapshot of sample stats. + Histogram::SampleSet snapshot; + histogram.SnapshotSample(&snapshot); + const std::string& histogram_name = histogram.histogram_name(); + + int corruption = histogram.FindCorruption(snapshot); + + // Crash if we detect that our histograms have been overwritten. This may be + // a fair distance from the memory smasher, but we hope to correlate these + // crashes with other events, such as plugins, or usage patterns, etc. + if (Histogram::BUCKET_ORDER_ERROR & corruption) { + // The checksum should have caught this, so crash separately if it didn't. + CHECK_NE(0, Histogram::RANGE_CHECKSUM_ERROR & corruption); + CHECK(false); // Crash for the bucket order corruption. + } + // Checksum corruption might not have caused order corruption. + CHECK_EQ(0, Histogram::RANGE_CHECKSUM_ERROR & corruption); + + if (corruption) { + NOTREACHED(); + histogram_flattener_->InconsistencyDetected(corruption); + // Don't record corrupt data to metrics survices. + if (NULL == inconsistencies_.get()) + inconsistencies_.reset(new ProblemMap); + int old_corruption = (*inconsistencies_)[histogram_name]; + if (old_corruption == (corruption | old_corruption)) + return; // We've already seen this corruption for this histogram. + (*inconsistencies_)[histogram_name] |= corruption; + histogram_flattener_->UniqueInconsistencyDetected(corruption); + return; + } + + // Find the already recorded stats, or create an empty set. Remove from our + // snapshot anything that we've already recorded. + LoggedSampleMap::iterator it = logged_samples_.find(histogram_name); + Histogram::SampleSet* already_logged; + if (logged_samples_.end() == it) { + // Add new entry + already_logged = &logged_samples_[histogram.histogram_name()]; + already_logged->Resize(histogram); // Complete initialization. + } else { + already_logged = &(it->second); + int64 discrepancy(already_logged->TotalCount() - + already_logged->redundant_count()); + if (discrepancy) { + NOTREACHED(); // Already_logged has become corrupt. + int problem = static_cast<int>(discrepancy); + if (problem != discrepancy) + problem = INT_MAX; + histogram_flattener_->SnapshotProblemResolved(problem); + // With no valid baseline, we'll act like we've recorded everything in our + // snapshot. + already_logged->Subtract(*already_logged); + already_logged->Add(snapshot); + } + // Deduct any stats we've already logged from our snapshot. + snapshot.Subtract(*already_logged); + } + + // Snapshot now contains only a delta to what we've already_logged. + if (snapshot.redundant_count() > 0) { + histogram_flattener_->RecordDelta(histogram, snapshot); + // Add new data into our running total. + already_logged->Add(snapshot); + } +} +} // namespace base diff --git a/base/metrics/histogram_snapshot_manager.h b/base/metrics/histogram_snapshot_manager.h new file mode 100644 index 0000000..a945ac7 --- /dev/null +++ b/base/metrics/histogram_snapshot_manager.h @@ -0,0 +1,60 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_METRICS_HISTOGRAM_SNAPSHOT_MANAGER_H_ +#define BASE_METRICS_HISTOGRAM_SNAPSHOT_MANAGER_H_ + +#include <map> +#include <string> + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/metrics/histogram.h" +#include "base/metrics/histogram_flattener.h" + +namespace base { + +// HistogramSnapshotManager handles the logistics of gathering up available +// histograms for recording either to disk or for transmission (such as from +// renderer to browser, or from browser to UMA upload). Since histograms can sit +// in memory for an extended period of time, and are vulnerable to memory +// corruption, this class also validates as much rendundancy as it can before +// calling for the marginal change (a.k.a., delta) in a histogram to be +// recorded. +class BASE_EXPORT HistogramSnapshotManager { + public: + explicit HistogramSnapshotManager(HistogramFlattener* histogram_flattener); + virtual ~HistogramSnapshotManager(); + + // Snapshot all histograms, and ask |histogram_flattener_| to record the + // delta. The arguments allow selecting only a subset of histograms for + // recording, or to set a flag in each recorded histogram. + void PrepareDeltas(base::Histogram::Flags flags_to_set, bool record_only_uma); + + private: + // Maintain a map of histogram names to the sample stats we've recorded. + typedef std::map<std::string, base::Histogram::SampleSet> LoggedSampleMap; + // List of histograms names, and their encontered corruptions. + typedef std::map<std::string, int> ProblemMap; + + // Snapshot this histogram, and record the delta. + void PrepareDelta(const base::Histogram& histogram); + + // For histograms, track what we've already recorded (as a sample for + // each histogram) so that we can record only the delta with the next log. + LoggedSampleMap logged_samples_; + + // List of histograms found corrupt to be corrupt, and their problems. + scoped_ptr<ProblemMap> inconsistencies_; + + // |histogram_flattener_| handles the logistics of recording the histogram + // deltas. + HistogramFlattener* histogram_flattener_; // Weak. + + DISALLOW_COPY_AND_ASSIGN(HistogramSnapshotManager); +}; + +} // namespace base + +#endif // BASE_METRICS_HISTOGRAM_SNAPSHOT_MANAGER_H_ |