Home | History | Annotate | Download | only in performance_monitor
      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
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/performance_monitor/startup_timer.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/logging.h"
      9 #include "base/strings/string_number_conversions.h"
     10 #include "chrome/browser/chrome_notification_types.h"
     11 #include "chrome/browser/performance_monitor/database.h"
     12 #include "chrome/browser/performance_monitor/performance_monitor.h"
     13 #include "content/public/browser/browser_thread.h"
     14 #include "content/public/browser/notification_details.h"
     15 #include "content/public/browser/notification_service.h"
     16 #include "content/public/browser/notification_source.h"
     17 #include "content/public/browser/notification_types.h"
     18 
     19 namespace performance_monitor {
     20 
     21 namespace {
     22 // Needed because Database::AddMetric is overloaded, so base::Bind doesn't work.
     23 void AddMetricToDatabaseOnBackgroundThread(Database* database,
     24                                            const Metric& metric) {
     25   database->AddMetric(metric);
     26 }
     27 
     28 }  // namespace
     29 
     30 // static
     31 StartupTimer* StartupTimer::g_startup_timer_ = NULL;
     32 
     33 StartupTimer::StartupTimer() : startup_begin_(base::TimeTicks::Now()),
     34                                startup_type_(STARTUP_NORMAL),
     35                                performance_monitor_initialized_(false) {
     36   CHECK(!g_startup_timer_);
     37   g_startup_timer_ = this;
     38 
     39   // We need this check because, under certain rare circumstances,
     40   // NotificationService::current() will return null, and this will cause a
     41   // segfault in NotificationServiceImpl::AddObserver(). Currently, this only
     42   // happens as a result of the child process launched by BrowserMainTest.
     43   // WarmConnectionFieldTrial_Invalid.
     44   if (content::NotificationService::current()) {
     45     registrar_.Add(this, chrome::NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED,
     46                    content::NotificationService::AllSources());
     47   }
     48 }
     49 
     50 StartupTimer::~StartupTimer() {
     51   DCHECK(this == g_startup_timer_);
     52   g_startup_timer_ = NULL;
     53 }
     54 
     55 bool StartupTimer::SignalStartupComplete(StartupType startup_type) {
     56   DCHECK(elapsed_startup_time_ == base::TimeDelta());
     57 
     58   startup_type_ = startup_type;
     59 
     60   elapsed_startup_time_ =
     61       base::TimeTicks::Now() - total_pause_ - startup_begin_;
     62 
     63   if (performance_monitor_initialized_)
     64     InsertElapsedStartupTime();
     65 
     66   return true;
     67 }
     68 
     69 // static
     70 void StartupTimer::PauseTimer() {
     71   // Check that the timer is not already paused.
     72   DCHECK(g_startup_timer_->pause_started_ == base::TimeTicks());
     73 
     74   g_startup_timer_->pause_started_ = base::TimeTicks::Now();
     75 }
     76 
     77 // static
     78 void StartupTimer::UnpauseTimer() {
     79   // Check that the timer has been paused.
     80   DCHECK(g_startup_timer_->pause_started_ != base::TimeTicks());
     81 
     82   g_startup_timer_->total_pause_ += base::TimeTicks::Now() -
     83                                     g_startup_timer_->pause_started_;
     84 
     85   g_startup_timer_->pause_started_ = base::TimeTicks();
     86 }
     87 
     88 void StartupTimer::Observe(int type,
     89                            const content::NotificationSource& source,
     90                            const content::NotificationDetails& details) {
     91   CHECK(type == chrome::NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED);
     92   performance_monitor_initialized_ = true;
     93   if (elapsed_startup_time_ != base::TimeDelta())
     94     InsertElapsedStartupTime();
     95   if (elapsed_session_restore_times_.size())
     96     InsertElapsedSessionRestoreTime();
     97 }
     98 
     99 // static
    100 void StartupTimer::SetElapsedSessionRestoreTime(
    101     const base::TimeDelta& elapsed_session_restore_time) {
    102   g_startup_timer_->elapsed_session_restore_times_.push_back(
    103       elapsed_session_restore_time);
    104 
    105   if (g_startup_timer_->performance_monitor_initialized_)
    106     g_startup_timer_->InsertElapsedSessionRestoreTime();
    107 }
    108 
    109 void StartupTimer::InsertElapsedStartupTime() {
    110   content::BrowserThread::PostBlockingPoolSequencedTask(
    111       Database::kDatabaseSequenceToken,
    112       FROM_HERE,
    113       base::Bind(
    114           &AddMetricToDatabaseOnBackgroundThread,
    115           base::Unretained(PerformanceMonitor::GetInstance()->database()),
    116           Metric(startup_type_ == STARTUP_NORMAL ? METRIC_STARTUP_TIME
    117                                                  : METRIC_TEST_STARTUP_TIME,
    118                  base::Time::Now(),
    119                  static_cast<double>(
    120                      elapsed_startup_time_.ToInternalValue()))));
    121 }
    122 
    123 void StartupTimer::InsertElapsedSessionRestoreTime() {
    124   for (std::vector<base::TimeDelta>::const_iterator iter =
    125            elapsed_session_restore_times_.begin();
    126        iter != elapsed_session_restore_times_.end(); ++iter) {
    127     content::BrowserThread::PostBlockingPoolSequencedTask(
    128         Database::kDatabaseSequenceToken,
    129         FROM_HERE,
    130         base::Bind(
    131             &AddMetricToDatabaseOnBackgroundThread,
    132             base::Unretained(PerformanceMonitor::GetInstance()->database()),
    133             Metric(METRIC_SESSION_RESTORE_TIME,
    134                    base::Time::Now(),
    135                    static_cast<double>(iter->ToInternalValue()))));
    136   }
    137 }
    138 
    139 }  // namespace performance_monitor
    140