Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: base/metrics/histogram_snapshot_manager.cc

Issue 1485763002: Merge multiple histogram snapshots into single one for reporting. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@shared-histograms
Patch Set: added merge test Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/metrics/histogram_snapshot_manager.h" 5 #include "base/metrics/histogram_snapshot_manager.h"
6 6
7 #include "base/memory/scoped_ptr.h" 7 #include "base/memory/scoped_ptr.h"
8 #include "base/metrics/histogram_flattener.h" 8 #include "base/metrics/histogram_flattener.h"
9 #include "base/metrics/histogram_samples.h" 9 #include "base/metrics/histogram_samples.h"
10 #include "base/metrics/statistics_recorder.h" 10 #include "base/metrics/statistics_recorder.h"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 12
13 namespace {
14 const int kNewInconsistency = (int)0x80000000;
15 } // namespace
16
13 namespace base { 17 namespace base {
14 18
15 HistogramSnapshotManager::HistogramSnapshotManager( 19 HistogramSnapshotManager::HistogramSnapshotManager(
16 HistogramFlattener* histogram_flattener) 20 HistogramFlattener* histogram_flattener)
17 : histogram_flattener_(histogram_flattener) { 21 : histogram_flattener_(histogram_flattener) {
18 DCHECK(histogram_flattener_); 22 DCHECK(histogram_flattener_);
19 } 23 }
20 24
21 HistogramSnapshotManager::~HistogramSnapshotManager() { 25 HistogramSnapshotManager::~HistogramSnapshotManager() {
22 STLDeleteValues(&logged_samples_);
23 } 26 }
24 27
25 void HistogramSnapshotManager::PrepareDelta(const HistogramBase& histogram) { 28 void HistogramSnapshotManager::StartDeltas() {
29 #ifdef DEBUG
30 for (HashInfoMap::iterator iter = known_histograms_.begin();
31 iter != known_histograms_.end();
32 ++iter) {
33 CHECK(!iter->second.histogram);
34 CHECK(!iter->second.accumulated);
35 CHECK(!(iter->second.inconsistencies & kNewInconsistency));
36 }
37 #endif
38 }
39
40 void HistogramSnapshotManager::PrepareDelta(const HistogramBase* histogram) {
26 DCHECK(histogram_flattener_); 41 DCHECK(histogram_flattener_);
27 42
28 // Get up-to-date snapshot of sample stats. 43 // Get up-to-date snapshot of sample stats.
29 scoped_ptr<HistogramSamples> snapshot(histogram.SnapshotSamples()); 44 scoped_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
30 const std::string& histogram_name = histogram.histogram_name();
31 const uint64_t histogram_hash = histogram.name_hash();
32 45
33 int corruption = histogram.FindCorruption(*snapshot); 46 // Get information known about this histogram.
47 const std::string& histogram_name = histogram->histogram_name();
48 SampleInfo& sample_info = known_histograms_[histogram->name_hash()];
Alexei Svitkine (slow) 2015/12/04 18:30:11 Nit: Make this a pointer, since non-const refs are
bcwhite 2015/12/08 17:32:18 Done.
49 if (sample_info.histogram) {
50 DCHECK_EQ(sample_info.histogram->histogram_name(), histogram_name)
51 << "hash collision";
52 } else {
53 // First time this histogram has been seen; datafill.
54 sample_info.histogram = histogram;
55 }
34 56
35 // Crash if we detect that our histograms have been overwritten. This may be 57 // Crash if we detect that our histograms have been overwritten. This may be
36 // a fair distance from the memory smasher, but we hope to correlate these 58 // a fair distance from the memory smasher, but we hope to correlate these
37 // crashes with other events, such as plugins, or usage patterns, etc. 59 // crashes with other events, such as plugins, or usage patterns, etc.
60 int corruption = histogram->FindCorruption(*snapshot);
38 if (HistogramBase::BUCKET_ORDER_ERROR & corruption) { 61 if (HistogramBase::BUCKET_ORDER_ERROR & corruption) {
39 // The checksum should have caught this, so crash separately if it didn't. 62 // The checksum should have caught this, so crash separately if it didn't.
40 CHECK_NE(0, HistogramBase::RANGE_CHECKSUM_ERROR & corruption); 63 CHECK_NE(0, HistogramBase::RANGE_CHECKSUM_ERROR & corruption);
41 CHECK(false); // Crash for the bucket order corruption. 64 CHECK(false); // Crash for the bucket order corruption.
42 } 65 }
43 // Checksum corruption might not have caused order corruption. 66 // Checksum corruption might not have caused order corruption.
44 CHECK_EQ(0, HistogramBase::RANGE_CHECKSUM_ERROR & corruption); 67 CHECK_EQ(0, HistogramBase::RANGE_CHECKSUM_ERROR & corruption);
45 68
46 // Note, at this point corruption can only be COUNT_HIGH_ERROR or 69 // Note, at this point corruption can only be COUNT_HIGH_ERROR or
47 // COUNT_LOW_ERROR and they never arise together, so we don't need to extract 70 // COUNT_LOW_ERROR and they never arise together, so we don't need to extract
48 // bits from corruption. 71 // bits from corruption.
49 if (corruption) { 72 if (corruption) {
50 DLOG(ERROR) << "Histogram: " << histogram_name 73 DLOG(ERROR) << "Histogram \"" << histogram_name
51 << " has data corruption: " << corruption; 74 << "\" has data corruption: " << corruption;
52 histogram_flattener_->InconsistencyDetected( 75 histogram_flattener_->InconsistencyDetected(
53 static_cast<HistogramBase::Inconsistency>(corruption)); 76 static_cast<HistogramBase::Inconsistency>(corruption));
54 // Don't record corrupt data to metrics services. 77 // Don't record corrupt data to metrics services.
55 int old_corruption = inconsistencies_[histogram_hash]; 78 const int old_corruption = sample_info.inconsistencies;
56 if (old_corruption == (corruption | old_corruption)) 79 if (old_corruption == (corruption | old_corruption))
57 return; // We've already seen this corruption for this histogram. 80 return; // We've already seen this corruption for this histogram.
58 inconsistencies_[histogram_hash] |= corruption; 81 sample_info.inconsistencies |= corruption | kNewInconsistency;
59 histogram_flattener_->UniqueInconsistencyDetected( 82 // TODO(bcwhite): Can we clear the inconsistency for future collection?
60 static_cast<HistogramBase::Inconsistency>(corruption));
61 return; 83 return;
62 } 84 }
63 85
64 HistogramSamples* to_log; 86 if (!sample_info.accumulated) {
65 std::map<uint64_t, HistogramSamples*>::iterator it = 87 // This histogram has not been seen before; add a new entry.
66 logged_samples_.find(histogram_hash); 88 sample_info.accumulated = snapshot.release();
67 if (it == logged_samples_.end()) { 89 } else {
68 to_log = snapshot.release(); 90 // There are previous values from this histogram; add them together.
91 sample_info.accumulated->Add(*snapshot);
92 }
93 }
69 94
70 // This histogram has not been logged before, add a new entry. 95 void HistogramSnapshotManager::FinishDeltas() {
71 logged_samples_[histogram_hash] = to_log; 96 // Iterate over all known histograms to see what should be recorded.
72 } else { 97 for (HashInfoMap::iterator iter = known_histograms_.begin();
73 HistogramSamples* already_logged = it->second; 98 iter != known_histograms_.end();
74 InspectLoggedSamplesInconsistency(*snapshot, already_logged); 99 ++iter) {
Alexei Svitkine (slow) 2015/12/04 18:30:11 Nit: Can this use C++11 for syntax?
bcwhite 2015/12/08 17:32:18 Done.
75 snapshot->Subtract(*already_logged); 100 SampleInfo& sample_info = iter->second;
76 already_logged->Add(*snapshot); 101
77 to_log = snapshot.get(); 102 // First, record any histograms in which corruption was detected.
103 if (sample_info.inconsistencies & kNewInconsistency) {
104 sample_info.inconsistencies &= ~kNewInconsistency;
105 histogram_flattener_->UniqueInconsistencyDetected(
106 static_cast<HistogramBase::Inconsistency>(
107 sample_info.inconsistencies));
108 }
109
110 // Second, record actual sample data.
111 if (sample_info.accumulated) {
112 if (sample_info.logged) {
113 // Subtract the previous report from this one and report that. Since
114 // the existing sum will be required for the next reporting cycle,
115 // perform subtraction in-place with the previous values (to be
116 // released later). LOGGED = CURRENT - LOGGED = -LOGGED + CURRENT
117 InspectLoggedSamplesInconsistency(*sample_info.accumulated,
118 sample_info.logged.get());
119 sample_info.logged->Negate();
120 sample_info.logged->Add(*sample_info.accumulated);
121 } else {
122 // This histogram has no previous report; log as-is.
123 sample_info.logged.reset(sample_info.accumulated);
124 sample_info.accumulated = nullptr;
125 }
126
127 if (sample_info.logged->TotalCount() > 0) {
128 histogram_flattener_->RecordDelta(*sample_info.histogram,
129 *sample_info.logged.get());
130 }
131
132 if (sample_info.accumulated) {
133 sample_info.logged.reset(sample_info.accumulated);
134 sample_info.accumulated = nullptr;
135 }
136 } else if (sample_info.logged) {
137 DLOG(ERROR) << "Histogram \"" << sample_info.histogram->histogram_name()
138 << "\" was lost since previous report";
139 sample_info.logged.reset();
140 }
78 } 141 }
79
80 if (to_log->TotalCount() > 0)
81 histogram_flattener_->RecordDelta(histogram, *to_log);
82 } 142 }
83 143
84 void HistogramSnapshotManager::InspectLoggedSamplesInconsistency( 144 void HistogramSnapshotManager::InspectLoggedSamplesInconsistency(
85 const HistogramSamples& new_snapshot, 145 const HistogramSamples& new_snapshot,
86 HistogramSamples* logged_samples) { 146 HistogramSamples* logged_samples) {
87 HistogramBase::Count discrepancy = 147 HistogramBase::Count discrepancy =
88 logged_samples->TotalCount() - logged_samples->redundant_count(); 148 logged_samples->TotalCount() - logged_samples->redundant_count();
89 if (!discrepancy) 149 if (!discrepancy)
90 return; 150 return;
91 151
92 histogram_flattener_->InconsistencyDetectedInLoggedCount(discrepancy); 152 histogram_flattener_->InconsistencyDetectedInLoggedCount(discrepancy);
93 if (discrepancy > Histogram::kCommonRaceBasedCountMismatch) { 153 if (discrepancy > Histogram::kCommonRaceBasedCountMismatch) {
94 // Fix logged_samples. 154 // Fix logged_samples.
95 logged_samples->Subtract(*logged_samples); 155 logged_samples->Subtract(*logged_samples);
96 logged_samples->Add(new_snapshot); 156 logged_samples->Add(new_snapshot);
97 } 157 }
98 } 158 }
99 159
100 } // namespace base 160 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698