summaryrefslogtreecommitdiffstats
path: root/components/startup_metric_utils/startup_metric_utils.cc
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/startup_metric_utils.cc
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/startup_metric_utils.cc')
-rw-r--r--components/startup_metric_utils/startup_metric_utils.cc169
1 files changed, 169 insertions, 0 deletions
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