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() && |
| 43 (iter_->second->flags() & HistogramBase::kIsPersistent)) { |
| 44 // This operator will continue to skip until a non-persistent histogram |
| 45 // is found. |
| 46 operator++(); |
| 47 } |
40 } | 48 } |
41 | 49 |
42 StatisticsRecorder::HistogramIterator::HistogramIterator( | 50 StatisticsRecorder::HistogramIterator::HistogramIterator( |
43 const HistogramIterator& rhs) | 51 const HistogramIterator& rhs) |
44 : iter_(rhs.iter_), | 52 : iter_(rhs.iter_), |
45 include_persistent_(rhs.include_persistent_) { | 53 include_persistent_(rhs.include_persistent_) { |
46 } | 54 } |
47 | 55 |
48 StatisticsRecorder::HistogramIterator::~HistogramIterator() {} | 56 StatisticsRecorder::HistogramIterator::~HistogramIterator() {} |
49 | 57 |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 | 288 |
281 for (const auto& entry : *ranges_) { | 289 for (const auto& entry : *ranges_) { |
282 for (const auto& range_entry : *entry.second) { | 290 for (const auto& range_entry : *entry.second) { |
283 output->push_back(range_entry); | 291 output->push_back(range_entry); |
284 } | 292 } |
285 } | 293 } |
286 } | 294 } |
287 | 295 |
288 // static | 296 // static |
289 HistogramBase* StatisticsRecorder::FindHistogram(base::StringPiece name) { | 297 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 | 298 // 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 | 299 // call back into this object to register histograms. Those called methods |
299 // will acquire the lock at that time. | 300 // will acquire the lock at that time. |
300 GlobalHistogramAllocator* allocator = GlobalHistogramAllocator::Get(); | 301 ImportGlobalPersistentHistograms(); |
301 if (allocator) | |
302 allocator->ImportHistogramsToStatisticsRecorder(); | |
303 | 302 |
| 303 if (lock_ == NULL) |
| 304 return NULL; |
304 base::AutoLock auto_lock(*lock_); | 305 base::AutoLock auto_lock(*lock_); |
305 if (histograms_ == NULL) | 306 if (histograms_ == NULL) |
306 return NULL; | 307 return NULL; |
307 | 308 |
308 HistogramMap::iterator it = histograms_->find(name); | 309 HistogramMap::iterator it = histograms_->find(name); |
309 if (histograms_->end() == it) | 310 if (histograms_->end() == it) |
310 return NULL; | 311 return NULL; |
311 return it->second; | 312 return it->second; |
312 } | 313 } |
313 | 314 |
314 // static | 315 // static |
315 StatisticsRecorder::HistogramIterator StatisticsRecorder::begin( | 316 StatisticsRecorder::HistogramIterator StatisticsRecorder::begin( |
316 bool include_persistent) { | 317 bool include_persistent) { |
| 318 ImportGlobalPersistentHistograms(); |
317 return HistogramIterator(histograms_->begin(), include_persistent); | 319 return HistogramIterator(histograms_->begin(), include_persistent); |
318 } | 320 } |
319 | 321 |
320 // static | 322 // static |
321 StatisticsRecorder::HistogramIterator StatisticsRecorder::end() { | 323 StatisticsRecorder::HistogramIterator StatisticsRecorder::end() { |
322 return HistogramIterator(histograms_->end(), true); | 324 return HistogramIterator(histograms_->end(), true); |
323 } | 325 } |
324 | 326 |
325 // static | 327 // static |
326 void StatisticsRecorder::GetSnapshot(const std::string& query, | 328 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. | 418 // can't "delete" it; call the destructor explicitly. |
417 DCHECK(g_statistics_recorder_.private_instance_); | 419 DCHECK(g_statistics_recorder_.private_instance_); |
418 g_statistics_recorder_.Get().~StatisticsRecorder(); | 420 g_statistics_recorder_.Get().~StatisticsRecorder(); |
419 | 421 |
420 // Now the ugly part. There's no official way to release a LazyInstance once | 422 // 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 | 423 // created so it's necessary to clear out an internal variable which |
422 // shouldn't be publicly visible but is for initialization reasons. | 424 // shouldn't be publicly visible but is for initialization reasons. |
423 g_statistics_recorder_.private_instance_ = 0; | 425 g_statistics_recorder_.private_instance_ = 0; |
424 } | 426 } |
425 | 427 |
| 428 // static |
| 429 void StatisticsRecorder::ImportGlobalPersistentHistograms() { |
| 430 if (lock_ == NULL) |
| 431 return; |
| 432 |
| 433 // Import histograms from known persistent storage. Histograms could have |
| 434 // been added by other processes and they must be fetched and recognized |
| 435 // locally. If the persistent memory segment is not shared between processes, |
| 436 // this call does nothing. |
| 437 GlobalHistogramAllocator* allocator = GlobalHistogramAllocator::Get(); |
| 438 if (allocator) |
| 439 allocator->ImportHistogramsToStatisticsRecorder(); |
| 440 } |
| 441 |
426 // This singleton instance should be started during the single threaded portion | 442 // 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 | 443 // of main(), and hence it is not thread safe. It initializes globals to |
428 // provide support for all future calls. | 444 // provide support for all future calls. |
429 StatisticsRecorder::StatisticsRecorder() { | 445 StatisticsRecorder::StatisticsRecorder() { |
430 if (lock_ == NULL) { | 446 if (lock_ == NULL) { |
431 // This will leak on purpose. It's the only way to make sure we won't race | 447 // 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 | 448 // against the static uninitialization of the module while one of our |
433 // static methods relying on the lock get called at an inappropriate time | 449 // 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 | 450 // 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 | 451 // 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 | 501 // static |
486 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; | 502 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; |
487 // static | 503 // static |
488 StatisticsRecorder::CallbackMap* StatisticsRecorder::callbacks_ = NULL; | 504 StatisticsRecorder::CallbackMap* StatisticsRecorder::callbacks_ = NULL; |
489 // static | 505 // static |
490 StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL; | 506 StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL; |
491 // static | 507 // static |
492 base::Lock* StatisticsRecorder::lock_ = NULL; | 508 base::Lock* StatisticsRecorder::lock_ = NULL; |
493 | 509 |
494 } // namespace base | 510 } // namespace base |
OLD | NEW |