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