OLD | NEW |
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" |
(...skipping 13 matching lines...) Expand all Loading... |
24 } | 24 } |
25 | 25 |
26 HistogramSnapshotManager::~HistogramSnapshotManager() { | 26 HistogramSnapshotManager::~HistogramSnapshotManager() { |
27 } | 27 } |
28 | 28 |
29 void HistogramSnapshotManager::StartDeltas() { | 29 void HistogramSnapshotManager::StartDeltas() { |
30 // Ensure that start/finish calls to not get nested. | 30 // Ensure that start/finish calls to not get nested. |
31 DCHECK(!preparing_deltas_); | 31 DCHECK(!preparing_deltas_); |
32 preparing_deltas_ = true; | 32 preparing_deltas_ = true; |
33 | 33 |
| 34 DCHECK(owned_histograms_.empty()); |
| 35 |
34 #ifdef DEBUG | 36 #ifdef DEBUG |
35 for (auto iter : known_histograms) { | 37 for (auto iter : known_histograms) { |
36 CHECK(!iter->second.histogram); | 38 CHECK(!iter->second.histogram); |
37 CHECK(!iter->second.accumulated); | 39 CHECK(!iter->second.accumulated); |
38 CHECK(!(iter->second.inconsistencies & kNewInconsistency)); | 40 CHECK(!(iter->second.inconsistencies & kNewInconsistency)); |
39 } | 41 } |
40 #endif | 42 #endif |
41 } | 43 } |
42 | 44 |
43 void HistogramSnapshotManager::PrepareDelta(HistogramBase* histogram) { | 45 void HistogramSnapshotManager::PrepareDelta(HistogramBase* histogram) { |
44 PrepareSamples(histogram, histogram->SnapshotDelta()); | 46 PrepareSamples(histogram, histogram->SnapshotDelta(), false); |
| 47 } |
| 48 |
| 49 void HistogramSnapshotManager::PrepareDeltaTakingOwnership( |
| 50 HistogramBase* histogram) { |
| 51 PrepareSamples(histogram, histogram->SnapshotDelta(), true); |
45 } | 52 } |
46 | 53 |
47 void HistogramSnapshotManager::PrepareOnce(const HistogramBase* histogram) { | 54 void HistogramSnapshotManager::PrepareOnce(const HistogramBase* histogram) { |
48 PrepareSamples(histogram, histogram->SnapshotSamples()); | 55 PrepareSamples(histogram, histogram->SnapshotSamples(), false); |
| 56 } |
| 57 |
| 58 void HistogramSnapshotManager::PrepareOnceTakingOwnership( |
| 59 const HistogramBase* histogram) { |
| 60 PrepareSamples(histogram, histogram->SnapshotSamples(), true); |
49 } | 61 } |
50 | 62 |
51 void HistogramSnapshotManager::PrepareSamples( | 63 void HistogramSnapshotManager::PrepareSamples( |
52 const HistogramBase* histogram, | 64 const HistogramBase* histogram, |
53 scoped_ptr<HistogramSamples> samples) { | 65 scoped_ptr<HistogramSamples> samples, |
| 66 bool take_ownership) { |
54 DCHECK(histogram_flattener_); | 67 DCHECK(histogram_flattener_); |
| 68 scoped_ptr<const HistogramBase> owned_histogram; |
55 | 69 |
56 // Get information known about this histogram. | 70 // Get information known about this histogram. |
57 SampleInfo* sample_info = &known_histograms_[histogram->name_hash()]; | 71 SampleInfo* sample_info = &known_histograms_[histogram->name_hash()]; |
58 if (sample_info->histogram) { | 72 if (sample_info->histogram) { |
59 DCHECK_EQ(sample_info->histogram->histogram_name(), | 73 DCHECK_EQ(sample_info->histogram->histogram_name(), |
60 histogram->histogram_name()) << "hash collision"; | 74 histogram->histogram_name()) << "hash collision"; |
| 75 // Passed histogram won't be needed past end of this method so store |
| 76 // it in a scoped_ptr that will release it when returning. |
| 77 if (take_ownership) |
| 78 owned_histogram.reset(histogram); |
61 } else { | 79 } else { |
62 // First time this histogram has been seen; datafill. | 80 // First time this histogram has been seen; datafill. |
63 sample_info->histogram = histogram; | 81 sample_info->histogram = histogram; |
| 82 // The histogram data will be needed up until "finished" so store |
| 83 // in member vector for releasing when that is done. |
| 84 if (take_ownership) |
| 85 owned_histograms_.push_back(histogram); |
64 } | 86 } |
65 | 87 |
66 // Crash if we detect that our histograms have been overwritten. This may be | 88 // Crash if we detect that our histograms have been overwritten. This may be |
67 // a fair distance from the memory smasher, but we hope to correlate these | 89 // a fair distance from the memory smasher, but we hope to correlate these |
68 // crashes with other events, such as plugins, or usage patterns, etc. | 90 // crashes with other events, such as plugins, or usage patterns, etc. |
69 int corruption = histogram->FindCorruption(*samples); | 91 int corruption = histogram->FindCorruption(*samples); |
70 if (HistogramBase::BUCKET_ORDER_ERROR & corruption) { | 92 if (HistogramBase::BUCKET_ORDER_ERROR & corruption) { |
71 // The checksum should have caught this, so crash separately if it didn't. | 93 // The checksum should have caught this, so crash separately if it didn't. |
72 CHECK_NE(0, HistogramBase::RANGE_CHECKSUM_ERROR & corruption); | 94 CHECK_NE(0, HistogramBase::RANGE_CHECKSUM_ERROR & corruption); |
73 CHECK(false); // Crash for the bucket order corruption. | 95 CHECK(false); // Crash for the bucket order corruption. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 } | 146 } |
125 delete sample_info->accumulated; | 147 delete sample_info->accumulated; |
126 sample_info->accumulated = nullptr; | 148 sample_info->accumulated = nullptr; |
127 } | 149 } |
128 | 150 |
129 // The Histogram pointer must be cleared at this point because the owner | 151 // The Histogram pointer must be cleared at this point because the owner |
130 // is only required to keep it alive until FinishDeltas() completes. | 152 // is only required to keep it alive until FinishDeltas() completes. |
131 sample_info->histogram = nullptr; | 153 sample_info->histogram = nullptr; |
132 } | 154 } |
133 | 155 |
| 156 STLDeleteContainerPointers(owned_histograms_.begin(), |
| 157 owned_histograms_.end()); |
| 158 owned_histograms_.clear(); |
| 159 |
134 preparing_deltas_ = false; | 160 preparing_deltas_ = false; |
135 } | 161 } |
136 | 162 |
137 void HistogramSnapshotManager::InspectLoggedSamplesInconsistency( | 163 void HistogramSnapshotManager::InspectLoggedSamplesInconsistency( |
138 const HistogramSamples& new_snapshot, | 164 const HistogramSamples& new_snapshot, |
139 HistogramSamples* logged_samples) { | 165 HistogramSamples* logged_samples) { |
140 HistogramBase::Count discrepancy = | 166 HistogramBase::Count discrepancy = |
141 logged_samples->TotalCount() - logged_samples->redundant_count(); | 167 logged_samples->TotalCount() - logged_samples->redundant_count(); |
142 if (!discrepancy) | 168 if (!discrepancy) |
143 return; | 169 return; |
144 | 170 |
145 histogram_flattener_->InconsistencyDetectedInLoggedCount(discrepancy); | 171 histogram_flattener_->InconsistencyDetectedInLoggedCount(discrepancy); |
146 if (discrepancy > Histogram::kCommonRaceBasedCountMismatch) { | 172 if (discrepancy > Histogram::kCommonRaceBasedCountMismatch) { |
147 // Fix logged_samples. | 173 // Fix logged_samples. |
148 logged_samples->Subtract(*logged_samples); | 174 logged_samples->Subtract(*logged_samples); |
149 logged_samples->Add(new_snapshot); | 175 logged_samples->Add(new_snapshot); |
150 } | 176 } |
151 } | 177 } |
152 | 178 |
153 } // namespace base | 179 } // namespace base |
OLD | NEW |