| 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 |