summaryrefslogtreecommitdiffstats
path: root/components/startup_metric_utils
diff options
context:
space:
mode:
authoraberent@chromium.org <aberent@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-03 12:09:17 +0000
committeraberent@chromium.org <aberent@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-03 12:09:17 +0000
commit7a83dd07d761464a5da42721e0353d178a22e8fa (patch)
treef9569778b26ff7d9a68b2df1e88a6a2fc5b01f6c /components/startup_metric_utils
parent97b13a790979dce3f9dec99e6cefccfcc4de8ae5 (diff)
downloadchromium_src-7a83dd07d761464a5da42721e0353d178a22e8fa.zip
chromium_src-7a83dd07d761464a5da42721e0353d178a22e8fa.tar.gz
chromium_src-7a83dd07d761464a5da42721e0353d178a22e8fa.tar.bz2
Move startup_metric_utils.* to a new component
startup_metric_utils is currently in chrome/common, but is only used by the browser. It can't be in chrome/browser because it is used by browser/bookmarks, which is becoming a component. To fix this create a new startup_metrics_utils component. BUG=280523 Review URL: https://chromiumcodereview.appspot.com/23515005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@220932 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components/startup_metric_utils')
-rw-r--r--components/startup_metric_utils/OWNERS1
-rw-r--r--components/startup_metric_utils/startup_metric_utils.cc169
-rw-r--r--components/startup_metric_utils/startup_metric_utils.h70
3 files changed, 240 insertions, 0 deletions
diff --git a/components/startup_metric_utils/OWNERS b/components/startup_metric_utils/OWNERS
new file mode 100644
index 0000000..b112a84
--- /dev/null
+++ b/components/startup_metric_utils/OWNERS
@@ -0,0 +1 @@
+jeremy@chromium.org \ No newline at end of file
diff --git a/components/startup_metric_utils/startup_metric_utils.cc b/components/startup_metric_utils/startup_metric_utils.cc
new file mode 100644
index 0000000..b2ac1bc
--- /dev/null
+++ b/components/startup_metric_utils/startup_metric_utils.cc
@@ -0,0 +1,169 @@
+// Copyright 2013 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 "components/startup_metric_utils/startup_metric_utils.h"
+
+#include "base/containers/hash_tables.h"
+#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/histogram_base.h"
+#include "base/metrics/statistics_recorder.h"
+#include "base/synchronization/lock.h"
+#include "base/sys_info.h"
+#include "base/time/time.h"
+
+namespace {
+
+// Mark as volatile to defensively make sure usage is thread-safe.
+// Note that at the time of this writing, access is only on the UI thread.
+volatile bool g_non_browser_ui_displayed = false;
+
+base::Time* MainEntryPointTimeInternal() {
+ static base::Time main_start_time = base::Time::Now();
+ return &main_start_time;
+}
+
+typedef base::hash_map<std::string,base::TimeDelta> SubsystemStartupTimeHash;
+
+SubsystemStartupTimeHash* GetSubsystemStartupTimeHash() {
+ static SubsystemStartupTimeHash* slow_startup_time_hash =
+ new SubsystemStartupTimeHash;
+ return slow_startup_time_hash;
+}
+
+base::Lock* GetSubsystemStartupTimeHashLock() {
+ static base::Lock* slow_startup_time_hash_lock = new base::Lock;
+ return slow_startup_time_hash_lock;
+}
+
+bool g_main_entry_time_was_recorded = false;
+bool g_startup_stats_collection_finished = false;
+bool g_was_slow_startup = false;
+
+} // namespace
+
+namespace startup_metric_utils {
+
+bool WasNonBrowserUIDisplayed() {
+ return g_non_browser_ui_displayed;
+}
+
+void SetNonBrowserUIDisplayed() {
+ g_non_browser_ui_displayed = true;
+}
+
+void RecordMainEntryPointTime() {
+ DCHECK(!g_main_entry_time_was_recorded);
+ g_main_entry_time_was_recorded = true;
+ MainEntryPointTimeInternal();
+}
+
+#if defined(OS_ANDROID)
+void RecordSavedMainEntryPointTime(const base::Time& entry_point_time) {
+ DCHECK(!g_main_entry_time_was_recorded);
+ g_main_entry_time_was_recorded = true;
+ *MainEntryPointTimeInternal() = entry_point_time;
+}
+#endif // OS_ANDROID
+
+// Return the time recorded by RecordMainEntryPointTime().
+const base::Time MainEntryStartTime() {
+ DCHECK(g_main_entry_time_was_recorded);
+ return *MainEntryPointTimeInternal();
+}
+
+void OnBrowserStartupComplete(bool is_first_run) {
+ // Bail if uptime < 7 minutes, to filter out cases where Chrome may have been
+ // autostarted and the machine is under io pressure.
+ const int64 kSevenMinutesInMilliseconds =
+ base::TimeDelta::FromMinutes(7).InMilliseconds();
+ if (base::SysInfo::Uptime() < kSevenMinutesInMilliseconds) {
+ g_startup_stats_collection_finished = true;
+ return;
+ }
+
+ // The Startup.BrowserMessageLoopStartTime histogram recorded in
+ // chrome_browser_main.cc exhibits instability in the field which limits its
+ // usefulness in all scenarios except when we have a very large sample size.
+ // Attempt to mitigate this with a new metric:
+ // * Measure time from main entry rather than the OS' notion of process start
+ // time.
+ // * Only measure launches that occur 7 minutes after boot to try to avoid
+ // cases where Chrome is auto-started and IO is heavily loaded.
+ base::TimeDelta startup_time_from_main_entry =
+ base::Time::Now() - MainEntryStartTime();
+ if (is_first_run) {
+ UMA_HISTOGRAM_LONG_TIMES(
+ "Startup.BrowserMessageLoopStartTimeFromMainEntry.FirstRun",
+ startup_time_from_main_entry);
+ } else {
+ UMA_HISTOGRAM_LONG_TIMES(
+ "Startup.BrowserMessageLoopStartTimeFromMainEntry",
+ startup_time_from_main_entry);
+ }
+
+ // Record histograms for the subsystem times for startups > 10 seconds.
+ const base::TimeDelta kTenSeconds = base::TimeDelta::FromSeconds(10);
+ if (startup_time_from_main_entry < kTenSeconds) {
+ g_startup_stats_collection_finished = true;
+ return;
+ }
+
+ // If we got here this was what we consider to be a slow startup which we
+ // want to record stats for.
+ g_was_slow_startup = true;
+}
+
+void OnInitialPageLoadComplete() {
+ if (!g_was_slow_startup)
+ return;
+ DCHECK(!g_startup_stats_collection_finished);
+
+ const base::TimeDelta kStartupTimeMin(
+ base::TimeDelta::FromMilliseconds(1));
+ const base::TimeDelta kStartupTimeMax(base::TimeDelta::FromMinutes(5));
+ static const size_t kStartupTimeBuckets = 100;
+
+ // Set UMA flag for histograms outside chrome/ that can't use the
+ // ScopedSlowStartupUMA class.
+ base::HistogramBase* histogram =
+ base::StatisticsRecorder::FindHistogram("Startup.SlowStartupNSSInit");
+ if (histogram)
+ histogram->SetFlags(base::HistogramBase::kUmaTargetedHistogramFlag);
+
+ // Iterate over the stats recorded by ScopedSlowStartupUMA and create
+ // histograms for them.
+ base::AutoLock locker(*GetSubsystemStartupTimeHashLock());
+ SubsystemStartupTimeHash* time_hash = GetSubsystemStartupTimeHash();
+ for (SubsystemStartupTimeHash::iterator i = time_hash->begin();
+ i != time_hash->end();
+ ++i) {
+ const std::string histogram_name = i->first;
+ base::HistogramBase* counter = base::Histogram::FactoryTimeGet(
+ histogram_name,
+ kStartupTimeMin,
+ kStartupTimeMax,
+ kStartupTimeBuckets,
+ base::Histogram::kUmaTargetedHistogramFlag);
+ counter->AddTime(i->second);
+ }
+
+ g_startup_stats_collection_finished = true;
+}
+
+ScopedSlowStartupUMA::~ScopedSlowStartupUMA() {
+ if (g_startup_stats_collection_finished)
+ return;
+
+ base::AutoLock locker(*GetSubsystemStartupTimeHashLock());
+ SubsystemStartupTimeHash* hash = GetSubsystemStartupTimeHash();
+ // Only record the initial sample for a given histogram.
+ if (hash->find(histogram_name_) != hash->end())
+ return;
+
+ (*hash)[histogram_name_] =
+ base::TimeTicks::Now() - start_time_;
+}
+
+} // namespace startup_metric_utils
diff --git a/components/startup_metric_utils/startup_metric_utils.h b/components/startup_metric_utils/startup_metric_utils.h
new file mode 100644
index 0000000..594ad15
--- /dev/null
+++ b/components/startup_metric_utils/startup_metric_utils.h
@@ -0,0 +1,70 @@
+// Copyright 2013 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 COMPONENTS_STARTUP_METRIC_UTILS_STARTUP_METRIC_UTILS_H_
+#define COMPONENTS_STARTUP_METRIC_UTILS_STARTUP_METRIC_UTILS_H_
+
+#include <string>
+
+#include "base/time/time.h"
+
+// Utility functions to support metric collection for browser startup.
+
+namespace startup_metric_utils {
+
+// Returns true if any UI other than the browser window has been displayed
+// so far. Useful to test if UI has been displayed before the first browser
+// window was shown, which would invalidate any surrounding timing metrics.
+bool WasNonBrowserUIDisplayed();
+
+// Call this when displaying UI that might potentially delay the appearance
+// of the initial browser window on Chrome startup.
+//
+// Note on usage: This function is idempotent and its overhead is low enough
+// in comparison with UI display that it's OK to call it on every
+// UI invocation regardless of whether the browser window has already
+// been displayed or not.
+void SetNonBrowserUIDisplayed();
+
+// Call this as early as possible in the startup process to record a
+// timestamp.
+void RecordMainEntryPointTime();
+
+#if defined(OS_ANDROID)
+// On Android the entry point time is the time at which the Java code starts.
+// This is recorded on the Java side, and then passed to the C++ side once the
+// C++ library is loaded and running.
+void RecordSavedMainEntryPointTime(const base::Time& entry_point_time);
+#endif // OS_ANDROID
+
+// Called just before the message loop is about to start. Entry point to record
+// startup stats.
+// |is_first_run| - is the current launch part of a first run.
+void OnBrowserStartupComplete(bool is_first_run);
+
+// Called when the initial page load has finished in order to record startup
+// stats.
+void OnInitialPageLoadComplete();
+
+// Scoper that records the time period before it's destructed in a histogram
+// with the given name. The histogram is only recorded for slow chrome startups.
+// Useful for trying to figure out what parts of Chrome cause slow startup.
+class ScopedSlowStartupUMA {
+ public:
+ explicit ScopedSlowStartupUMA(const std::string& histogram_name)
+ : start_time_(base::TimeTicks::Now()),
+ histogram_name_(histogram_name) {}
+
+ ~ScopedSlowStartupUMA();
+
+ private:
+ const base::TimeTicks start_time_;
+ const std::string histogram_name_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedSlowStartupUMA);
+};
+
+} // namespace startup_metric_utils
+
+#endif // COMPONENTS_STARTUP_METRIC_UTILS_STARTUP_METRIC_UTILS_H_