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/statistics_recorder.h" | 5 #include "base/metrics/statistics_recorder.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "base/at_exit.h" | 9 #include "base/at_exit.h" |
10 #include "base/debug/leak_annotations.h" | 10 #include "base/debug/leak_annotations.h" |
(...skipping 19 matching lines...) Expand all Loading... | |
30 } | 30 } |
31 | 31 |
32 } // namespace | 32 } // namespace |
33 | 33 |
34 namespace base { | 34 namespace base { |
35 | 35 |
36 StatisticsRecorder::HistogramIterator::HistogramIterator( | 36 StatisticsRecorder::HistogramIterator::HistogramIterator( |
37 const HistogramMap::iterator& iter, bool include_persistent) | 37 const HistogramMap::iterator& iter, bool include_persistent) |
38 : iter_(iter), | 38 : iter_(iter), |
39 include_persistent_(include_persistent) { | 39 include_persistent_(include_persistent) { |
40 // The starting location could point to a persistent histogram when such | |
41 // is not wanted. If so, skip it. | |
42 if (!include_persistent_ && iter_ != histograms_->end() && | |
Alexei Svitkine (slow)
2016/04/11 14:51:34
Shouldn't this be a loop? What if the second entry
bcwhite
2016/04/12 00:32:02
operator++ already includes a loop that skips as a
Alexei Svitkine (slow)
2016/04/12 21:02:08
Makes sense. Maybe add a comment so it's clear whe
bcwhite
2016/04/13 12:59:45
Done.
| |
43 (iter_->second->flags() & HistogramBase::kIsPersistent)) { | |
44 operator++(); | |
45 } | |
40 } | 46 } |
41 | 47 |
42 StatisticsRecorder::HistogramIterator::HistogramIterator( | 48 StatisticsRecorder::HistogramIterator::HistogramIterator( |
43 const HistogramIterator& rhs) | 49 const HistogramIterator& rhs) |
44 : iter_(rhs.iter_), | 50 : iter_(rhs.iter_), |
45 include_persistent_(rhs.include_persistent_) { | 51 include_persistent_(rhs.include_persistent_) { |
46 } | 52 } |
47 | 53 |
48 StatisticsRecorder::HistogramIterator::~HistogramIterator() {} | 54 StatisticsRecorder::HistogramIterator::~HistogramIterator() {} |
49 | 55 |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
280 | 286 |
281 for (const auto& entry : *ranges_) { | 287 for (const auto& entry : *ranges_) { |
282 for (const auto& range_entry : *entry.second) { | 288 for (const auto& range_entry : *entry.second) { |
283 output->push_back(range_entry); | 289 output->push_back(range_entry); |
284 } | 290 } |
285 } | 291 } |
286 } | 292 } |
287 | 293 |
288 // static | 294 // static |
289 HistogramBase* StatisticsRecorder::FindHistogram(base::StringPiece name) { | 295 HistogramBase* StatisticsRecorder::FindHistogram(base::StringPiece name) { |
290 if (lock_ == NULL) | |
291 return NULL; | |
292 | |
293 // Import histograms from known persistent storage. Histograms could have | |
294 // been added by other processes and they must be fetched and recognized | |
295 // locally. If the persistent memory segment is not shared between processes, | |
296 // this call does nothing. | |
297 // This must be called *before* the lock is acquired below because it will | 296 // This must be called *before* the lock is acquired below because it will |
298 // call back into this object to register histograms. Those called methods | 297 // call back into this object to register histograms. Those called methods |
299 // will acquire the lock at that time. | 298 // will acquire the lock at that time. |
300 GlobalHistogramAllocator* allocator = GlobalHistogramAllocator::Get(); | 299 ImportGlobalPersistentHistograms(); |
301 if (allocator) | |
302 allocator->ImportHistogramsToStatisticsRecorder(); | |
303 | 300 |
301 if (lock_ == NULL) | |
302 return NULL; | |
304 base::AutoLock auto_lock(*lock_); | 303 base::AutoLock auto_lock(*lock_); |
305 if (histograms_ == NULL) | 304 if (histograms_ == NULL) |
306 return NULL; | 305 return NULL; |
307 | 306 |
308 HistogramMap::iterator it = histograms_->find(name); | 307 HistogramMap::iterator it = histograms_->find(name); |
309 if (histograms_->end() == it) | 308 if (histograms_->end() == it) |
310 return NULL; | 309 return NULL; |
311 return it->second; | 310 return it->second; |
312 } | 311 } |
313 | 312 |
314 // static | 313 // static |
315 StatisticsRecorder::HistogramIterator StatisticsRecorder::begin( | 314 StatisticsRecorder::HistogramIterator StatisticsRecorder::begin( |
316 bool include_persistent) { | 315 bool include_persistent) { |
316 ImportGlobalPersistentHistograms(); | |
317 return HistogramIterator(histograms_->begin(), include_persistent); | 317 return HistogramIterator(histograms_->begin(), include_persistent); |
318 } | 318 } |
319 | 319 |
320 // static | 320 // static |
321 StatisticsRecorder::HistogramIterator StatisticsRecorder::end() { | 321 StatisticsRecorder::HistogramIterator StatisticsRecorder::end() { |
322 return HistogramIterator(histograms_->end(), true); | 322 return HistogramIterator(histograms_->end(), true); |
323 } | 323 } |
324 | 324 |
325 // static | 325 // static |
326 void StatisticsRecorder::GetSnapshot(const std::string& query, | 326 void StatisticsRecorder::GetSnapshot(const std::string& query, |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
416 // can't "delete" it; call the destructor explicitly. | 416 // can't "delete" it; call the destructor explicitly. |
417 DCHECK(g_statistics_recorder_.private_instance_); | 417 DCHECK(g_statistics_recorder_.private_instance_); |
418 g_statistics_recorder_.Get().~StatisticsRecorder(); | 418 g_statistics_recorder_.Get().~StatisticsRecorder(); |
419 | 419 |
420 // Now the ugly part. There's no official way to release a LazyInstance once | 420 // Now the ugly part. There's no official way to release a LazyInstance once |
421 // created so it's necessary to clear out an internal variable which | 421 // created so it's necessary to clear out an internal variable which |
422 // shouldn't be publicly visible but is for initialization reasons. | 422 // shouldn't be publicly visible but is for initialization reasons. |
423 g_statistics_recorder_.private_instance_ = 0; | 423 g_statistics_recorder_.private_instance_ = 0; |
424 } | 424 } |
425 | 425 |
426 // static | |
427 void StatisticsRecorder::ImportGlobalPersistentHistograms() { | |
428 if (lock_ == NULL) | |
429 return; | |
430 | |
431 // Import histograms from known persistent storage. Histograms could have | |
432 // been added by other processes and they must be fetched and recognized | |
433 // locally. If the persistent memory segment is not shared between processes, | |
434 // this call does nothing. | |
435 GlobalHistogramAllocator* allocator = GlobalHistogramAllocator::Get(); | |
436 if (allocator) | |
437 allocator->ImportHistogramsToStatisticsRecorder(); | |
438 } | |
439 | |
426 // This singleton instance should be started during the single threaded portion | 440 // This singleton instance should be started during the single threaded portion |
427 // of main(), and hence it is not thread safe. It initializes globals to | 441 // of main(), and hence it is not thread safe. It initializes globals to |
428 // provide support for all future calls. | 442 // provide support for all future calls. |
429 StatisticsRecorder::StatisticsRecorder() { | 443 StatisticsRecorder::StatisticsRecorder() { |
430 if (lock_ == NULL) { | 444 if (lock_ == NULL) { |
431 // This will leak on purpose. It's the only way to make sure we won't race | 445 // This will leak on purpose. It's the only way to make sure we won't race |
432 // against the static uninitialization of the module while one of our | 446 // against the static uninitialization of the module while one of our |
433 // static methods relying on the lock get called at an inappropriate time | 447 // static methods relying on the lock get called at an inappropriate time |
434 // during the termination phase. Since it's a static data member, we will | 448 // during the termination phase. Since it's a static data member, we will |
435 // leak one per process, which would be similar to the instance allocated | 449 // leak one per process, which would be similar to the instance allocated |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
485 // static | 499 // static |
486 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; | 500 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; |
487 // static | 501 // static |
488 StatisticsRecorder::CallbackMap* StatisticsRecorder::callbacks_ = NULL; | 502 StatisticsRecorder::CallbackMap* StatisticsRecorder::callbacks_ = NULL; |
489 // static | 503 // static |
490 StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL; | 504 StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL; |
491 // static | 505 // static |
492 base::Lock* StatisticsRecorder::lock_ = NULL; | 506 base::Lock* StatisticsRecorder::lock_ = NULL; |
493 | 507 |
494 } // namespace base | 508 } // namespace base |
OLD | NEW |