OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/persistent_sample_map.h" | 5 #include "base/metrics/persistent_sample_map.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
9 #include "base/metrics/histogram_macros.h" | 9 #include "base/metrics/histogram_macros.h" |
10 #include "base/metrics/persistent_histogram_allocator.h" | 10 #include "base/metrics/persistent_histogram_allocator.h" |
11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
12 | 12 |
13 namespace base { | 13 namespace base { |
14 | 14 |
15 typedef HistogramBase::Count Count; | 15 typedef HistogramBase::Count Count; |
16 typedef HistogramBase::Sample Sample; | 16 typedef HistogramBase::Sample Sample; |
17 | 17 |
18 namespace { | 18 namespace { |
19 | 19 |
20 enum NegativeSampleReason { | 20 enum NegativeSampleReason { |
21 PERSISTENT_SPARSE_HAVE_LOGGED_BUT_NOT_SAMPLE, | 21 PERSISTENT_SPARSE_HAVE_LOGGED_BUT_NOT_SAMPLE, |
22 PERSISTENT_SPARSE_SAMPLE_LESS_THAN_LOGGED, | 22 PERSISTENT_SPARSE_SAMPLE_LESS_THAN_LOGGED, |
| 23 PERSISTENT_SPARSE_ADDED_NEGATIVE_COUNT, |
| 24 PERSISTENT_SPARSE_ADD_WENT_NEGATIVE, |
| 25 PERSISTENT_SPARSE_ADD_OVERFLOW, |
23 MAX_NEGATIVE_SAMPLE_REASONS | 26 MAX_NEGATIVE_SAMPLE_REASONS |
24 }; | 27 }; |
25 | 28 |
26 // An iterator for going through a PersistentSampleMap. The logic here is | 29 // An iterator for going through a PersistentSampleMap. The logic here is |
27 // identical to that of SampleMapIterator but with different data structures. | 30 // identical to that of SampleMapIterator but with different data structures. |
28 // Changes here likely need to be duplicated there. | 31 // Changes here likely need to be duplicated there. |
29 class PersistentSampleMapIterator : public SampleCountIterator { | 32 class PersistentSampleMapIterator : public SampleCountIterator { |
30 public: | 33 public: |
31 typedef std::map<HistogramBase::Sample, HistogramBase::Count*> | 34 typedef std::map<HistogramBase::Sample, HistogramBase::Count*> |
32 SampleToCountMap; | 35 SampleToCountMap; |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 iter->Get(&min, &max, &count); | 193 iter->Get(&min, &max, &count); |
191 if (count == 0) | 194 if (count == 0) |
192 continue; | 195 continue; |
193 if (min + 1 != max) | 196 if (min + 1 != max) |
194 return false; // SparseHistogram only supports bucket with size 1. | 197 return false; // SparseHistogram only supports bucket with size 1. |
195 | 198 |
196 #if 0 // TODO(bcwhite) Re-enable efficient version after crbug.com/682680. | 199 #if 0 // TODO(bcwhite) Re-enable efficient version after crbug.com/682680. |
197 *GetOrCreateSampleCountStorage(min) += | 200 *GetOrCreateSampleCountStorage(min) += |
198 (op == HistogramSamples::ADD) ? count : -count; | 201 (op == HistogramSamples::ADD) ? count : -count; |
199 #else | 202 #else |
| 203 NegativeSampleReason reason = MAX_NEGATIVE_SAMPLE_REASONS; |
200 if (op == HistogramSamples::ADD) { | 204 if (op == HistogramSamples::ADD) { |
201 *GetOrCreateSampleCountStorage(min) += count; | 205 // Add should generally be adding only positive values. |
| 206 Count* local_count_ptr = GetOrCreateSampleCountStorage(min); |
| 207 if (count < 0) { |
| 208 reason = PERSISTENT_SPARSE_ADDED_NEGATIVE_COUNT; |
| 209 if (*local_count_ptr < -count) { |
| 210 reason = PERSISTENT_SPARSE_ADD_WENT_NEGATIVE; |
| 211 *local_count_ptr = 0; |
| 212 } |
| 213 } else { |
| 214 *local_count_ptr += count; |
| 215 if (*local_count_ptr < 0) |
| 216 reason = PERSISTENT_SPARSE_ADD_OVERFLOW; |
| 217 } |
202 } else { | 218 } else { |
203 // Subtract is used only for determining deltas when reporting which | 219 // Subtract is used only for determining deltas when reporting which |
204 // means that it's in the "logged" iterator. It should have an active | 220 // means that it's in the "logged" iterator. It should have an active |
205 // sample record and thus there is no need to try to create one. | 221 // sample record and thus there is no need to try to create one. |
206 NegativeSampleReason reason = MAX_NEGATIVE_SAMPLE_REASONS; | 222 Count* local_count_ptr = GetSampleCountStorage(min); |
207 Count* bucket = GetSampleCountStorage(min); | 223 if (local_count_ptr == nullptr) { |
208 if (bucket == nullptr) { | |
209 reason = PERSISTENT_SPARSE_HAVE_LOGGED_BUT_NOT_SAMPLE; | 224 reason = PERSISTENT_SPARSE_HAVE_LOGGED_BUT_NOT_SAMPLE; |
210 } else { | 225 } else { |
211 if (*bucket < count) { | 226 if (*local_count_ptr < count) { |
212 reason = PERSISTENT_SPARSE_SAMPLE_LESS_THAN_LOGGED; | 227 reason = PERSISTENT_SPARSE_SAMPLE_LESS_THAN_LOGGED; |
213 *bucket = 0; | 228 *local_count_ptr = 0; |
214 } else { | 229 } else { |
215 *bucket -= count; | 230 *local_count_ptr -= count; |
216 } | 231 } |
217 } | 232 } |
218 if (reason != MAX_NEGATIVE_SAMPLE_REASONS) { | 233 } |
219 UMA_HISTOGRAM_ENUMERATION("UMA.NegativeSamples.Reason", reason, | 234 if (reason != MAX_NEGATIVE_SAMPLE_REASONS) { |
220 MAX_NEGATIVE_SAMPLE_REASONS); | 235 NOTREACHED(); |
221 } | 236 UMA_HISTOGRAM_ENUMERATION("UMA.NegativeSamples.Reason", reason, |
| 237 MAX_NEGATIVE_SAMPLE_REASONS); |
222 } | 238 } |
223 #endif | 239 #endif |
224 } | 240 } |
225 return true; | 241 return true; |
226 } | 242 } |
227 | 243 |
228 Count* PersistentSampleMap::GetSampleCountStorage(Sample value) { | 244 Count* PersistentSampleMap::GetSampleCountStorage(Sample value) { |
229 // If |value| is already in the map, just return that. | 245 // If |value| is already in the map, just return that. |
230 auto it = sample_counts_.find(value); | 246 auto it = sample_counts_.find(value); |
231 if (it != sample_counts_.end()) | 247 if (it != sample_counts_.end()) |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 found_count = &record->count; | 328 found_count = &record->count; |
313 if (!import_everything) | 329 if (!import_everything) |
314 break; | 330 break; |
315 } | 331 } |
316 } | 332 } |
317 | 333 |
318 return found_count; | 334 return found_count; |
319 } | 335 } |
320 | 336 |
321 } // namespace base | 337 } // namespace base |
OLD | NEW |