summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorrdevlin.cronin@chromium.org <rdevlin.cronin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-09 20:30:24 +0000
committerrdevlin.cronin@chromium.org <rdevlin.cronin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-09 20:30:24 +0000
commit0c1c47564b667a988d28e53fb7d276f20866796b (patch)
tree89daf84f415c95ce022ea36cbb0f07c8c1636483 /chrome
parentbeee7a9de8c1fb91f05ffa7eeb657a5679c1dfe4 (diff)
downloadchromium_src-0c1c47564b667a988d28e53fb7d276f20866796b.zip
chromium_src-0c1c47564b667a988d28e53fb7d276f20866796b.tar.gz
chromium_src-0c1c47564b667a988d28e53fb7d276f20866796b.tar.bz2
Add Startup Timing to CPM
Add in support for timing chrome's startup and session restore times. BUG=130212 TEST=Included Review URL: https://chromiumcodereview.appspot.com/10834015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150881 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/chrome_browser_main.cc11
-rw-r--r--chrome/browser/chrome_browser_main.h9
-rw-r--r--chrome/browser/performance_monitor/constants.cc21
-rw-r--r--chrome/browser/performance_monitor/constants.h17
-rw-r--r--chrome/browser/performance_monitor/metric_details.cc18
-rw-r--r--chrome/browser/performance_monitor/metric_details.h3
-rw-r--r--chrome/browser/performance_monitor/performance_monitor_browsertest.cc94
-rw-r--r--chrome/browser/performance_monitor/startup_timer.cc137
-rw-r--r--chrome/browser/performance_monitor/startup_timer.h103
-rw-r--r--chrome/browser/sessions/session_restore.cc3
-rw-r--r--chrome/browser/sessions/session_restore_browsertest.cc7
-rw-r--r--chrome/browser/sessions/session_service.h1
-rw-r--r--chrome/browser/sessions/session_service_test_helper.cc6
-rw-r--r--chrome/browser/sessions/session_service_test_helper.h3
-rw-r--r--chrome/browser/ui/startup/startup_browser_creator_impl.cc13
-rw-r--r--chrome/chrome_browser.gypi2
16 files changed, 439 insertions, 9 deletions
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 4b07ad4..d8eac6e 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -56,6 +56,7 @@
#include "chrome/browser/notifications/desktop_notification_service.h"
#include "chrome/browser/notifications/desktop_notification_service_factory.h"
#include "chrome/browser/page_cycler/page_cycler.h"
+#include "chrome/browser/performance_monitor/startup_timer.h"
#include "chrome/browser/plugin_prefs.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/prefs/pref_value_store.h"
@@ -498,6 +499,7 @@ ChromeBrowserMainParts::ChromeBrowserMainParts(
result_code_(content::RESULT_CODE_NORMAL_EXIT),
startup_watcher_(new StartupTimeBomb()),
shutdown_watcher_(new ShutdownWatcherHelper()),
+ startup_timer_(new performance_monitor::StartupTimer()),
browser_field_trials_(parameters.command_line),
record_search_engine_(false),
translate_manager_(NULL),
@@ -1383,6 +1385,10 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
PostBrowserStart();
if (parameters().ui_task) {
+ // We end the startup timer here if we have parameters to run, because we
+ // never start to run the main loop (where we normally stop the timer).
+ startup_timer_->SignalStartupComplete(
+ performance_monitor::StartupTimer::STARTUP_TEST);
parameters().ui_task->Run();
delete parameters().ui_task;
run_message_loop_ = false;
@@ -1403,10 +1409,13 @@ bool ChromeBrowserMainParts::MainMessageLoopRun(int* result_code) {
if (!run_message_loop_)
return true; // Don't run the default message loop.
- // This should be invoked as close to the start of the browser's
+ // These should be invoked as close to the start of the browser's
// UI thread message loop as possible to get a stable measurement
// across versions.
RecordBrowserStartupTime();
+ startup_timer_->SignalStartupComplete(
+ performance_monitor::StartupTimer::STARTUP_NORMAL);
+
DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type());
#if !defined(USE_AURA) && defined(TOOLKIT_VIEWS)
views::AcceleratorHandler accelerator_handler;
diff --git a/chrome/browser/chrome_browser_main.h b/chrome/browser/chrome_browser_main.h
index 1b16d9c..c820c16 100644
--- a/chrome/browser/chrome_browser_main.h
+++ b/chrome/browser/chrome_browser_main.h
@@ -44,6 +44,10 @@ namespace content {
struct MainFunctionParams;
}
+namespace performance_monitor {
+class StartupTimer;
+}
+
class ChromeBrowserMainParts : public content::BrowserMainParts {
public:
virtual ~ChromeBrowserMainParts();
@@ -132,6 +136,11 @@ class ChromeBrowserMainParts : public content::BrowserMainParts {
// it is destroyed last.
scoped_ptr<ShutdownWatcherHelper> shutdown_watcher_;
+ // A timer to hold data regarding startup and session restore times for
+ // PerformanceMonitor so that we don't have to start the entire
+ // PerformanceMonitor at browser startup.
+ scoped_ptr<performance_monitor::StartupTimer> startup_timer_;
+
// Creating this object starts tracking the creation and deletion of Task
// instance. This MUST be done before main_message_loop, so that it is
// destroyed after the main_message_loop.
diff --git a/chrome/browser/performance_monitor/constants.cc b/chrome/browser/performance_monitor/constants.cc
index 27d660b..3c167cc 100644
--- a/chrome/browser/performance_monitor/constants.cc
+++ b/chrome/browser/performance_monitor/constants.cc
@@ -53,4 +53,25 @@ const char kMetricSharedMemoryUsageDescription[] =
const char kMetricSharedMemoryUsageUnits[] = "bytes";
const double kMetricSharedMemoryUsageTickSize = 10000000.0;
+// Startup Time
+const char kMetricStartupTimeName[] = "Startup Time";
+const char kMetricStartupTimeDescription[] =
+ "The startup time measured in microseconds";
+const char kMetricStartupTimeUnits[] = "microseconds";
+const double kMetricStartupTimeTickSize = 5000000;
+
+// Test Startup Time
+const char kMetricTestStartupTimeName[] = "Test Startup Time";
+const char kMetricTestStartupTimeDescription[] =
+ "The startup time of test startups measured in microseconds";
+const char kMetricTestStartupTimeUnits[] = "microseconds";
+const double kMetricTestStartupTimeTickSize = 5000000;
+
+// Session Restore Time
+const char kMetricSessionRestoreTimeName[] = "Session Restore Time";
+const char kMetricSessionRestoreTimeDescription[] =
+ "The session restore time measured in microseconds";
+const char kMetricSessionRestoreTimeUnits[] = "microseconds";
+const double kMetricSessionRestoreTimeTickSize = 5000000;
+
} // namespace performance_monitor
diff --git a/chrome/browser/performance_monitor/constants.h b/chrome/browser/performance_monitor/constants.h
index 9065538..dbf153d 100644
--- a/chrome/browser/performance_monitor/constants.h
+++ b/chrome/browser/performance_monitor/constants.h
@@ -24,15 +24,32 @@ extern const char kMetricCPUUsageName[];
extern const char kMetricCPUUsageDescription[];
extern const char kMetricCPUUsageUnits[];
extern const double kMetricCPUUsageTickSize;
+
extern const char kMetricPrivateMemoryUsageName[];
extern const char kMetricPrivateMemoryUsageDescription[];
extern const char kMetricPrivateMemoryUsageUnits[];
extern const double kMetricPrivateMemoryUsageTickSize;
+
extern const char kMetricSharedMemoryUsageName[];
extern const char kMetricSharedMemoryUsageDescription[];
extern const char kMetricSharedMemoryUsageUnits[];
extern const double kMetricSharedMemoryUsageTickSize;
+extern const char kMetricStartupTimeName[];
+extern const char kMetricStartupTimeDescription[];
+extern const char kMetricStartupTimeUnits[];
+extern const double kMetricStartupTimeTickSize;
+
+extern const char kMetricTestStartupTimeName[];
+extern const char kMetricTestStartupTimeDescription[];
+extern const char kMetricTestStartupTimeUnits[];
+extern const double kMetricTestStartupTimeTickSize;
+
+extern const char kMetricSessionRestoreTimeName[];
+extern const char kMetricSessionRestoreTimeDescription[];
+extern const char kMetricSessionRestoreTimeUnits[];
+extern const double kMetricSessionRestoreTimeTickSize;
+
} // namespace performance_monitor
#endif // CHROME_BROWSER_PERFORMANCE_MONITOR_CONSTANTS_H_
diff --git a/chrome/browser/performance_monitor/metric_details.cc b/chrome/browser/performance_monitor/metric_details.cc
index 2767728..613bfdf 100644
--- a/chrome/browser/performance_monitor/metric_details.cc
+++ b/chrome/browser/performance_monitor/metric_details.cc
@@ -31,6 +31,24 @@ const MetricDetails kMetricDetailsList[] = {
kMetricSharedMemoryUsageUnits,
kMetricSharedMemoryUsageTickSize
},
+ {
+ kMetricStartupTimeName,
+ kMetricStartupTimeDescription,
+ kMetricStartupTimeUnits,
+ kMetricStartupTimeTickSize
+ },
+ {
+ kMetricTestStartupTimeName,
+ kMetricTestStartupTimeDescription,
+ kMetricTestStartupTimeUnits,
+ kMetricTestStartupTimeTickSize
+ },
+ {
+ kMetricSessionRestoreTimeName,
+ kMetricSessionRestoreTimeDescription,
+ kMetricSessionRestoreTimeUnits,
+ kMetricSessionRestoreTimeTickSize
+ }
};
COMPILE_ASSERT(ARRAYSIZE_UNSAFE(kMetricDetailsList) == METRIC_NUMBER_OF_METRICS,
metric_names_incorrect_size);
diff --git a/chrome/browser/performance_monitor/metric_details.h b/chrome/browser/performance_monitor/metric_details.h
index 10f1ff0..ba0f357 100644
--- a/chrome/browser/performance_monitor/metric_details.h
+++ b/chrome/browser/performance_monitor/metric_details.h
@@ -14,6 +14,9 @@ enum MetricType {
METRIC_CPU_USAGE,
METRIC_PRIVATE_MEMORY_USAGE,
METRIC_SHARED_MEMORY_USAGE,
+ METRIC_STARTUP_TIME,
+ METRIC_TEST_STARTUP_TIME,
+ METRIC_SESSION_RESTORE_TIME,
METRIC_NUMBER_OF_METRICS
};
diff --git a/chrome/browser/performance_monitor/performance_monitor_browsertest.cc b/chrome/browser/performance_monitor/performance_monitor_browsertest.cc
index abbb4b6..acc5612 100644
--- a/chrome/browser/performance_monitor/performance_monitor_browsertest.cc
+++ b/chrome/browser/performance_monitor/performance_monitor_browsertest.cc
@@ -11,17 +11,25 @@
#include "base/string_number_conversions.h"
#include "base/threading/sequenced_worker_pool.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/performance_monitor/constants.h"
-#include "chrome/browser/performance_monitor/database.h"
-#include "chrome/browser/performance_monitor/performance_monitor.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/unpacked_installer.h"
+#include "chrome/browser/performance_monitor/constants.h"
+#include "chrome/browser/performance_monitor/database.h"
+#include "chrome/browser/performance_monitor/performance_monitor.h"
+#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/sessions/session_restore.h"
+#include "chrome/browser/sessions/session_service.h"
+#include "chrome/browser/sessions/session_service_test_helper.h"
+#include "chrome/browser/sessions/session_service_factory.h"
#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_notification_types.h"
@@ -35,13 +43,20 @@
#include "content/public/browser/notification_service.h"
#include "content/public/common/page_transition_types.h"
#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
+#if defined(OS_MACOSX)
+#include "base/mac/scoped_nsautorelease_pool.h"
+#endif
+
using extensions::Extension;
using performance_monitor::Event;
namespace {
+const base::TimeDelta kMaxStartupTime = base::TimeDelta::FromMinutes(3);
+
// Helper struct to store the information of an extension; this is needed if the
// pointer to the extension ever becomes invalid (e.g., if we uninstall the
// extension).
@@ -305,6 +320,54 @@ class PerformanceMonitorUncleanExitBrowserTest
std::string second_profile_name_;
};
+class PerformanceMonitorSessionRestoreBrowserTest
+ : public PerformanceMonitorBrowserTest {
+ public:
+ virtual void SetUpOnMainThread() OVERRIDE {
+ SessionStartupPref pref(SessionStartupPref::LAST);
+ SessionStartupPref::SetStartupPref(browser()->profile(), pref);
+#if defined(OS_CHROMEOS) || defined (OS_MACOSX)
+ // Undo the effect of kBrowserAliveWithNoWindows in defaults.cc so that we
+ // can get these test to work without quitting.
+ SessionServiceTestHelper helper(
+ SessionServiceFactory::GetForProfile(browser()->profile()));
+ helper.SetForceBrowserNotAliveWithNoWindows(true);
+ helper.ReleaseService();
+#endif
+
+ PerformanceMonitorBrowserTest::SetUpOnMainThread();
+ }
+
+ Browser* QuitBrowserAndRestore(Browser* browser, int expected_tab_count) {
+ Profile* profile = browser->profile();
+
+ // Close the browser.
+ g_browser_process->AddRefModule();
+ content::WindowedNotificationObserver observer(
+ chrome::NOTIFICATION_BROWSER_CLOSED,
+ content::NotificationService::AllSources());
+ browser->window()->Close();
+#if defined(OS_MACOSX)
+ // BrowserWindowController depends on the auto release pool being recycled
+ // in the message loop to delete itself, which frees the Browser object
+ // which fires this event.
+ AutoreleasePool()->Recycle();
+#endif
+ observer.Wait();
+
+ // Create a new window, which should trigger session restore.
+ ui_test_utils::BrowserAddedObserver window_observer;
+ content::TestNavigationObserver navigation_observer(
+ content::NotificationService::AllSources(), NULL, expected_tab_count);
+ chrome::NewEmptyWindow(profile);
+ Browser* new_browser = window_observer.WaitForSingleNewBrowser();
+ navigation_observer.Wait();
+ g_browser_process->ReleaseModule();
+
+ return new_browser;
+ }
+};
+
// Test that PerformanceMonitor will correctly record an extension installation
// event.
IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, InstallExtensionEvent) {
@@ -631,4 +694,29 @@ IN_PROC_BROWSER_TEST_F(PerformanceMonitorUncleanExitBrowserTest,
ASSERT_EQ(second_profile_name_, event_profile);
}
+IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, StartupTime) {
+ Database::MetricInfoVector metrics = GetStats(METRIC_TEST_STARTUP_TIME);
+
+ ASSERT_EQ(1u, metrics.size());
+ ASSERT_LT(metrics[0].value, kMaxStartupTime.ToInternalValue());
+}
+
+IN_PROC_BROWSER_TEST_F(PerformanceMonitorSessionRestoreBrowserTest,
+ StartupWithSessionRestore) {
+ ui_test_utils::NavigateToURL(
+ browser(),
+ ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
+ FilePath(FILE_PATH_LITERAL("title1.html"))));
+
+ QuitBrowserAndRestore(browser(), 1);
+
+ Database::MetricInfoVector metrics = GetStats(METRIC_TEST_STARTUP_TIME);
+ ASSERT_EQ(1u, metrics.size());
+ ASSERT_LT(metrics[0].value, kMaxStartupTime.ToInternalValue());
+
+ metrics = GetStats(METRIC_SESSION_RESTORE_TIME);
+ ASSERT_EQ(1u, metrics.size());
+ ASSERT_LT(metrics[0].value, kMaxStartupTime.ToInternalValue());
+}
+
} // namespace performance_monitor
diff --git a/chrome/browser/performance_monitor/startup_timer.cc b/chrome/browser/performance_monitor/startup_timer.cc
new file mode 100644
index 0000000..0af0a57
--- /dev/null
+++ b/chrome/browser/performance_monitor/startup_timer.cc
@@ -0,0 +1,137 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/performance_monitor/startup_timer.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "chrome/browser/performance_monitor/database.h"
+#include "chrome/browser/performance_monitor/performance_monitor.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
+#include "content/public/browser/notification_types.h"
+
+namespace performance_monitor {
+
+namespace {
+// Needed because Database::AddMetric is overloaded, so base::Bind doesn't work.
+void AddMetricToDatabaseOnBackgroundThread(Database* database,
+ MetricType metric,
+ std::string value) {
+ database->AddMetric(metric, value);
+}
+
+} // namespace
+
+// static
+StartupTimer* StartupTimer::g_startup_timer_ = NULL;
+
+StartupTimer::StartupTimer() : startup_begin_(base::TimeTicks::Now()),
+ startup_type_(STARTUP_NORMAL),
+ performance_monitor_initialized_(false) {
+ CHECK(!g_startup_timer_);
+ g_startup_timer_ = this;
+
+ // We need this check because, under certain rare circumstances,
+ // NotificationService::current() will return null, and this will cause a
+ // segfault in NotificationServiceImpl::AddObserver(). Currently, this only
+ // happens as a result of the child process launched by BrowserMainTest.
+ // WarmConnectionFieldTrial_Invalid.
+ if (content::NotificationService::current()) {
+ registrar_.Add(this, chrome::NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED,
+ content::NotificationService::AllSources());
+ }
+}
+
+StartupTimer::~StartupTimer() {
+ DCHECK(this == g_startup_timer_);
+ g_startup_timer_ = NULL;
+}
+
+bool StartupTimer::SignalStartupComplete(StartupType startup_type) {
+ DCHECK(elapsed_startup_time_ == base::TimeDelta());
+
+ startup_type_ = startup_type;
+
+ elapsed_startup_time_ =
+ base::TimeTicks::Now() - total_pause_ - startup_begin_;
+
+ if (performance_monitor_initialized_)
+ InsertElapsedStartupTime();
+
+ return true;
+}
+
+// static
+void StartupTimer::PauseTimer() {
+ // Check that the timer is not already paused.
+ DCHECK(g_startup_timer_->pause_started_ == base::TimeTicks());
+
+ g_startup_timer_->pause_started_ = base::TimeTicks::Now();
+}
+
+// static
+void StartupTimer::UnpauseTimer() {
+ // Check that the timer has been paused.
+ DCHECK(g_startup_timer_->pause_started_ != base::TimeTicks());
+
+ g_startup_timer_->total_pause_ += base::TimeTicks::Now() -
+ g_startup_timer_->pause_started_;
+
+ g_startup_timer_->pause_started_ = base::TimeTicks();
+}
+
+void StartupTimer::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ CHECK(type == chrome::NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED);
+ performance_monitor_initialized_ = true;
+ if (elapsed_startup_time_ != base::TimeDelta())
+ InsertElapsedStartupTime();
+ if (elapsed_session_restore_times_.size())
+ InsertElapsedSessionRestoreTime();
+}
+
+// static
+void StartupTimer::SetElapsedSessionRestoreTime(
+ const base::TimeDelta& elapsed_session_restore_time) {
+ g_startup_timer_->elapsed_session_restore_times_.push_back(
+ elapsed_session_restore_time);
+
+ if (g_startup_timer_->performance_monitor_initialized_)
+ g_startup_timer_->InsertElapsedSessionRestoreTime();
+}
+
+void StartupTimer::InsertElapsedStartupTime() {
+ content::BrowserThread::PostBlockingPoolSequencedTask(
+ Database::kDatabaseSequenceToken,
+ FROM_HERE,
+ base::Bind(
+ &AddMetricToDatabaseOnBackgroundThread,
+ base::Unretained(PerformanceMonitor::GetInstance()->database()),
+ startup_type_ == STARTUP_NORMAL ? METRIC_STARTUP_TIME
+ : METRIC_TEST_STARTUP_TIME,
+ base::Int64ToString(elapsed_startup_time_.ToInternalValue())));
+}
+
+void StartupTimer::InsertElapsedSessionRestoreTime() {
+ for (std::vector<base::TimeDelta>::const_iterator iter =
+ elapsed_session_restore_times_.begin();
+ iter != elapsed_session_restore_times_.end(); ++iter) {
+ content::BrowserThread::PostBlockingPoolSequencedTask(
+ Database::kDatabaseSequenceToken,
+ FROM_HERE,
+ base::Bind(
+ &AddMetricToDatabaseOnBackgroundThread,
+ base::Unretained(PerformanceMonitor::GetInstance()->database()),
+ METRIC_SESSION_RESTORE_TIME,
+ base::Int64ToString(iter->ToInternalValue())));
+ }
+}
+
+} // namespace performance_monitor
diff --git a/chrome/browser/performance_monitor/startup_timer.h b/chrome/browser/performance_monitor/startup_timer.h
new file mode 100644
index 0000000..2bab4db
--- /dev/null
+++ b/chrome/browser/performance_monitor/startup_timer.h
@@ -0,0 +1,103 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PERFORMANCE_MONITOR_STARTUP_TIMER_H_
+#define CHROME_BROWSER_PERFORMANCE_MONITOR_STARTUP_TIMER_H_
+
+#include "base/time.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+namespace performance_monitor {
+
+// This class is responsible for recording the startup and session restore times
+// (if applicable) for PerformanceMonitor. This allows us to initialize this
+// relatively small object early in the startup process, and start the whole of
+// PerformanceMonitor at a later time. StartupTimer will record the times and
+// insert them into PerformanceMonitor's database.
+class StartupTimer : public content::NotificationObserver {
+ public:
+ // Indicates the type of startup; i.e. either a normal startup or a testing
+ // environment.
+ enum StartupType {
+ STARTUP_NORMAL,
+ STARTUP_TEST
+ };
+
+ StartupTimer();
+ virtual ~StartupTimer();
+
+ // Inform StartupTimer that the startup process has been completed; stop the
+ // timer. Returns false if the timer has already stopped.
+ bool SignalStartupComplete(StartupType startup_type);
+
+ // Pauses the timer until UnpauseTimer() is called; any time spent within a
+ // pause does not count towards the measured startup time. This will DCHECK if
+ // PauseTimer() is called while paused or UnpauseTimer() is called while
+ // unpaused.
+ static void PauseTimer();
+ static void UnpauseTimer();
+
+ // content::NotificationObserver
+ // We keep track of whether or not PerformanceMonitor has been started via
+ // the PERFORMANCE_MONITOR_INITIALIZED notification; we need to know this so
+ // we know when to insert startup data into the database. We either insert
+ // data as we gather it (if PerformanceMonitor is started prior to data
+ // collection) or at the notification (if PerformanceMonitor is started
+ // later).
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ static void SetElapsedSessionRestoreTime(
+ const base::TimeDelta& elapsed_session_restore_time);
+
+ private:
+ // Insert the elapsed time measures into PerformanceMonitor's database.
+ void InsertElapsedStartupTime();
+ void InsertElapsedSessionRestoreTime();
+
+ // The time at which the startup process begins (the creation of
+ // ChromeBrowserMain).
+ base::TimeTicks startup_begin_;
+
+ // The time at which the timer was most recently paused, or null if the timer
+ // is not currently paused.
+ base::TimeTicks pause_started_;
+
+ // The total duration for which the timer has been paused.
+ base::TimeDelta total_pause_;
+
+ // A flag of whether or not this was a "normal" startup (e.g. whether or not
+ // this was in a testing environment, which would change the startup time
+ // values). If it is not a normal startup, we use a different metric.
+ StartupType startup_type_;
+
+ // The total duration of the startup process, minus any pauses.
+ base::TimeDelta elapsed_startup_time_;
+
+ // The total duration of the session restore(s), if any occurred. This is
+ // independent of the startup time, because:
+ // - If the user has auto-restore on, the restore is synchronous, and we pause
+ // the startup timer during the session restore; the restore will not
+ // interfere with startup timing.
+ // - If Chrome crashed and the user chooses to restore the crashed session,
+ // then the startup is already completed; the restore will not interfere
+ // with startup timing.
+ std::vector<base::TimeDelta> elapsed_session_restore_times_;
+
+ // Flag whether or not PerformanceMonitor has been fully started.
+ bool performance_monitor_initialized_;
+
+ content::NotificationRegistrar registrar_;
+
+ // The singleton of this class.
+ static StartupTimer* g_startup_timer_;
+
+ DISALLOW_COPY_AND_ASSIGN(StartupTimer);
+};
+
+} // namespace performance_monitor
+
+#endif // CHROME_BROWSER_PERFORMANCE_MONITOR_STARTUP_TIMER_H_
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc
index 7351544..2906eec 100644
--- a/chrome/browser/sessions/session_restore.cc
+++ b/chrome/browser/sessions/session_restore.cc
@@ -20,6 +20,7 @@
#include "base/stringprintf.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/performance_monitor/startup_timer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sessions/session_service.h"
#include "chrome/browser/sessions/session_service_factory.h"
@@ -440,6 +441,8 @@ void TabLoader::HandleTabClosedOrLoaded(NavigationController* tab) {
if (tabs_loading_.empty() && tabs_to_load_.empty()) {
base::TimeDelta time_to_load =
base::TimeTicks::Now() - restore_started_;
+ performance_monitor::StartupTimer::SetElapsedSessionRestoreTime(
+ time_to_load);
UMA_HISTOGRAM_CUSTOM_TIMES(
"SessionRestore.AllTabsLoaded",
time_to_load,
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc
index 154bf0a..9155f82 100644
--- a/chrome/browser/sessions/session_restore_browsertest.cc
+++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -13,6 +13,7 @@
#include "chrome/browser/sessions/session_restore.h"
#include "chrome/browser/sessions/session_service.h"
#include "chrome/browser/sessions/session_service_factory.h"
+#include "chrome/browser/sessions/session_service_test_helper.h"
#include "chrome/browser/sessions/tab_restore_service.h"
#include "chrome/browser/sessions/tab_restore_service_factory.h"
#include "chrome/browser/ui/browser.h"
@@ -51,8 +52,10 @@ class SessionRestoreTest : public InProcessBrowserTest {
if (strcmp(test_info->name(), "NoSessionRestoreNewWindowChromeOS")) {
// Undo the effect of kBrowserAliveWithNoWindows in defaults.cc so that we
// can get these test to work without quitting.
- SessionServiceFactory::GetForProfile(browser()->profile())->
- force_browser_not_alive_with_no_windows_ = true;
+ SessionServiceTestHelper helper(
+ SessionServiceFactory::GetForProfile(browser()->profile()));
+ helper.SetForceBrowserNotAliveWithNoWindows(true);
+ helper.ReleaseService();
}
#endif
}
diff --git a/chrome/browser/sessions/session_service.h b/chrome/browser/sessions/session_service.h
index 97621cf..f40ad3a 100644
--- a/chrome/browser/sessions/session_service.h
+++ b/chrome/browser/sessions/session_service.h
@@ -52,7 +52,6 @@ class NavigationEntry;
// of the browser.
class SessionService : public BaseSessionService,
public content::NotificationObserver {
- friend class SessionRestoreTest;
friend class SessionServiceTestHelper;
public:
// Used to distinguish an application window from a normal one.
diff --git a/chrome/browser/sessions/session_service_test_helper.cc b/chrome/browser/sessions/session_service_test_helper.cc
index 2953e02..3f02a4c 100644
--- a/chrome/browser/sessions/session_service_test_helper.cc
+++ b/chrome/browser/sessions/session_service_test_helper.cc
@@ -50,6 +50,12 @@ void SessionServiceTestHelper::SetTabUserAgentOverride(
service()->SetTabUserAgentOverride(window_id, tab_id, user_agent_override);
}
+void SessionServiceTestHelper::SetForceBrowserNotAliveWithNoWindows(
+ bool force_browser_not_alive_with_no_windows) {
+ service()->force_browser_not_alive_with_no_windows_ =
+ force_browser_not_alive_with_no_windows;
+}
+
// Be sure and null out service to force closing the file.
void SessionServiceTestHelper::ReadWindows(
std::vector<SessionWindow*>* windows) {
diff --git a/chrome/browser/sessions/session_service_test_helper.h b/chrome/browser/sessions/session_service_test_helper.h
index 3419712..cccb1d3 100644
--- a/chrome/browser/sessions/session_service_test_helper.h
+++ b/chrome/browser/sessions/session_service_test_helper.h
@@ -43,6 +43,9 @@ class SessionServiceTestHelper {
const SessionID& tab_id,
const std::string& user_agent_override);
+ void SetForceBrowserNotAliveWithNoWindows(
+ bool force_browser_not_alive_with_no_windows);
+
// Reads the contents of the last session.
void ReadWindows(std::vector<SessionWindow*>* windows);
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index adcb2f3..4bb4994 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -29,6 +29,7 @@
#include "chrome/browser/net/predictor.h"
#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/browser/notifications/desktop_notification_service.h"
+#include "chrome/browser/performance_monitor/startup_timer.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/prefs/session_startup_pref.h"
@@ -606,8 +607,8 @@ bool StartupBrowserCreatorImpl::ProcessStartupURLs(
return false;
}
- uint32 restore_behavior = SessionRestore::SYNCHRONOUS |
- SessionRestore::ALWAYS_CREATE_TABBED_BROWSER;
+ uint32 restore_behavior = SessionRestore::SYNCHRONOUS |
+ SessionRestore::ALWAYS_CREATE_TABBED_BROWSER;
#if defined(OS_MACOSX)
// On Mac, when restoring a session with no windows, suppress the creation
// of a new window in the case where the system is launching Chrome via a
@@ -618,10 +619,18 @@ bool StartupBrowserCreatorImpl::ProcessStartupURLs(
}
#endif
+ // Pause the StartupTimer. Since the restore here is synchronous, we can
+ // keep these two metrics (browser startup time and session restore time)
+ // separate.
+ performance_monitor::StartupTimer::PauseTimer();
+
Browser* browser = SessionRestore::RestoreSession(profile_,
NULL,
restore_behavior,
urls_to_open);
+
+ performance_monitor::StartupTimer::UnpauseTimer();
+
AddInfoBarsIfNecessary(browser, chrome::startup::IS_PROCESS_STARTUP);
return true;
}
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 69a83a2..312608a 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1648,6 +1648,8 @@
'browser/performance_monitor/performance_monitor.h',
'browser/performance_monitor/performance_monitor_util.cc',
'browser/performance_monitor/performance_monitor_util.h',
+ 'browser/performance_monitor/startup_timer.cc',
+ 'browser/performance_monitor/startup_timer.h',
'browser/platform_util.h',
'browser/platform_util_android.cc',
'browser/platform_util_aura.cc',