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