| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/common/startup_metric_utils.h" | 5 #include "chrome/common/startup_metric_utils.h" |
| 6 | 6 |
| 7 #include "base/hash_tables.h" |
| 7 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/metrics/histogram.h" |
| 10 #include "base/synchronization/lock.h" |
| 11 #include "base/sys_info.h" |
| 8 #include "base/time.h" | 12 #include "base/time.h" |
| 9 | 13 |
| 10 namespace { | 14 namespace { |
| 11 | 15 |
| 12 // Mark as volatile to defensively make sure usage is thread-safe. | 16 // Mark as volatile to defensively make sure usage is thread-safe. |
| 13 // Note that at the time of this writing, access is only on the UI thread. | 17 // Note that at the time of this writing, access is only on the UI thread. |
| 14 static volatile bool g_non_browser_ui_displayed = false; | 18 volatile bool g_non_browser_ui_displayed = false; |
| 15 | 19 |
| 16 const base::Time* MainEntryPointTimeInternal() { | 20 const base::Time* MainEntryPointTimeInternal() { |
| 17 static base::Time main_start_time = base::Time::Now(); | 21 static base::Time main_start_time = base::Time::Now(); |
| 18 return &main_start_time; | 22 return &main_start_time; |
| 19 } | 23 } |
| 20 | 24 |
| 21 static bool g_main_entry_time_was_recorded = false; | 25 typedef base::hash_map<std::string,base::TimeDelta> SubsystemStartupTimeHash; |
| 26 |
| 27 SubsystemStartupTimeHash* GetSubsystemStartupTimeHash() { |
| 28 static SubsystemStartupTimeHash* slow_startup_time_hash = |
| 29 new SubsystemStartupTimeHash; |
| 30 return slow_startup_time_hash; |
| 31 } |
| 32 |
| 33 base::Lock* GetSubsystemStartupTimeHashLock() { |
| 34 static base::Lock* slow_startup_time_hash_lock = new base::Lock; |
| 35 return slow_startup_time_hash_lock; |
| 36 } |
| 37 |
| 38 bool g_main_entry_time_was_recorded = false; |
| 22 } // namespace | 39 } // namespace |
| 23 | 40 |
| 24 namespace startup_metric_utils { | 41 namespace startup_metric_utils { |
| 25 | 42 |
| 26 bool WasNonBrowserUIDisplayed() { | 43 bool WasNonBrowserUIDisplayed() { |
| 27 return g_non_browser_ui_displayed; | 44 return g_non_browser_ui_displayed; |
| 28 } | 45 } |
| 29 | 46 |
| 30 void SetNonBrowserUIDisplayed() { | 47 void SetNonBrowserUIDisplayed() { |
| 31 g_non_browser_ui_displayed = true; | 48 g_non_browser_ui_displayed = true; |
| 32 } | 49 } |
| 33 | 50 |
| 34 void RecordMainEntryPointTime() { | 51 void RecordMainEntryPointTime() { |
| 35 DCHECK(!g_main_entry_time_was_recorded); | 52 DCHECK(!g_main_entry_time_was_recorded); |
| 36 g_main_entry_time_was_recorded = true; | 53 g_main_entry_time_was_recorded = true; |
| 37 MainEntryPointTimeInternal(); | 54 MainEntryPointTimeInternal(); |
| 38 } | 55 } |
| 39 | 56 |
| 57 // Return the time recorded by RecordMainEntryPointTime(). |
| 40 const base::Time MainEntryStartTime() { | 58 const base::Time MainEntryStartTime() { |
| 41 DCHECK(g_main_entry_time_was_recorded); | 59 DCHECK(g_main_entry_time_was_recorded); |
| 42 return *MainEntryPointTimeInternal(); | 60 return *MainEntryPointTimeInternal(); |
| 43 } | 61 } |
| 44 | 62 |
| 63 void OnBrowserStartupComplete() { |
| 64 // Bail if uptime < 7 minutes, to filter out cases where Chrome may have been |
| 65 // autostarted and the machine is under io pressure. |
| 66 const int64 kSevenMinutesInMilliseconds = |
| 67 base::TimeDelta::FromMinutes(7).InMilliseconds(); |
| 68 if (base::SysInfo::Uptime() < kSevenMinutesInMilliseconds) |
| 69 return; |
| 70 |
| 71 const base::TimeDelta kStartupTimeMin(base::TimeDelta::FromMilliseconds(1)); |
| 72 const base::TimeDelta kStartupTimeMax(base::TimeDelta::FromMinutes(5)); |
| 73 static const size_t kStartupTimeBuckets(100); |
| 74 |
| 75 // The Startup.BrowserMessageLoopStartTime histogram recorded in |
| 76 // chrome_browser_main.cc exhibits instability in the field which limits its |
| 77 // usefulness in all scenarios except when we have a very large sample size. |
| 78 // Attempt to mitigate this with a new metric: |
| 79 // * Measure time from main entry rather than the OS' notion of process start |
| 80 // time. |
| 81 // * Only measure launches that occur 7 minutes after boot to try to avoid |
| 82 // cases where Chrome is auto-started and IO is heavily loaded. |
| 83 base::TimeDelta startup_time_from_main_entry = |
| 84 base::Time::Now() - MainEntryStartTime(); |
| 85 UMA_HISTOGRAM_LONG_TIMES( |
| 86 "Startup.BrowserMessageLoopStartTimeFromMainEntry", |
| 87 startup_time_from_main_entry); |
| 88 |
| 89 // Record histograms for the subsystem times for startups > 10 seconds. |
| 90 const base::TimeDelta kTenSeconds = base::TimeDelta::FromSeconds(10); |
| 91 if (startup_time_from_main_entry < kTenSeconds) |
| 92 return; |
| 93 { |
| 94 base::AutoLock locker(*GetSubsystemStartupTimeHashLock()); |
| 95 SubsystemStartupTimeHash* time_hash = GetSubsystemStartupTimeHash(); |
| 96 for (SubsystemStartupTimeHash::iterator i = time_hash->begin(); |
| 97 i != time_hash->end(); |
| 98 ++i) { |
| 99 const std::string histogram_name = i->first; |
| 100 base::Histogram* counter = base::Histogram::FactoryTimeGet( |
| 101 histogram_name, |
| 102 kStartupTimeMin, |
| 103 kStartupTimeMax, |
| 104 kStartupTimeBuckets, |
| 105 base::Histogram::kUmaTargetedHistogramFlag); |
| 106 counter->AddTime(i->second); |
| 107 } |
| 108 } |
| 109 } |
| 110 |
| 111 ScopedSlowStartupUMA::~ScopedSlowStartupUMA() { |
| 112 base::AutoLock locker(*GetSubsystemStartupTimeHashLock()); |
| 113 (*GetSubsystemStartupTimeHash())[histogram_name_] = |
| 114 base::TimeTicks::Now() - start_time_; |
| 115 } |
| 116 |
| 45 } // namespace startup_metric_utils | 117 } // namespace startup_metric_utils |
| OLD | NEW |