Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1018)

Unified Diff: components/startup_metric_utils/browser/startup_metric_utils.cc

Issue 1425263003: Use TimeTicks as much as possible in startup_metric_utils. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: ifdef thread priority dance out on Mac per lack of support in base Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/startup_metric_utils/browser/startup_metric_utils.cc
diff --git a/components/startup_metric_utils/browser/startup_metric_utils.cc b/components/startup_metric_utils/browser/startup_metric_utils.cc
index 122326e95daff16a888d4106c7d148d12afeb4d7..3f4144721d8c73ce73275ca3cc7232397f70ee1c 100644
--- a/components/startup_metric_utils/browser/startup_metric_utils.cc
+++ b/components/startup_metric_utils/browser/startup_metric_utils.cc
@@ -11,6 +11,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/sys_info.h"
+#include "base/threading/platform_thread.h"
#include "base/trace_event/trace_event.h"
#if defined(OS_WIN)
@@ -26,9 +27,15 @@ namespace {
// Note that at the time of this writing, access is only on the UI thread.
volatile bool g_non_browser_ui_displayed = false;
-base::LazyInstance<base::Time>::Leaky g_process_creation_time =
+base::LazyInstance<base::TimeTicks>::Leaky g_process_creation_ticks =
LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<base::TimeTicks>::Leaky g_main_entry_point_ticks =
+ LAZY_INSTANCE_INITIALIZER;
+
+// Only used by RecordMainEntryTimeHistogram(), should go away with it (do not
+// add new uses of this), see crbug.com/317481 for discussion on why it was kept
+// as-is for now.
base::LazyInstance<base::Time>::Leaky g_main_entry_point_time =
LAZY_INSTANCE_INITIALIZER;
@@ -176,19 +183,17 @@ bool GetHardFaultCountForCurrentProcess(uint32_t* hard_fault_count,
} \
}
-#define UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(type, basename, \
- begin_time, end_time) \
- { \
- UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(type, basename, \
- end_time - begin_time) \
- TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( \
- "startup", basename, 0, \
- StartupTimeToTimeTicks(begin_time).ToInternalValue(), "Temperature", \
- g_startup_temperature); \
- TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP1( \
- "startup", basename, 0, \
- StartupTimeToTimeTicks(end_time).ToInternalValue(), "Temperature", \
- g_startup_temperature); \
+#define UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( \
+ type, basename, begin_ticks, end_ticks) \
+ { \
+ UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(type, basename, \
+ end_ticks - begin_ticks) \
+ TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( \
+ "startup", basename, 0, begin_ticks.ToInternalValue(), "Temperature", \
+ g_startup_temperature); \
+ TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP1( \
+ "startup", basename, 0, end_ticks.ToInternalValue(), "Temperature", \
+ g_startup_temperature); \
}
// On Windows, records the number of hard-faults that have occurred in the
@@ -246,17 +251,42 @@ void RecordHardFaultHistogram(bool is_first_run) {
}
// Converts a base::Time value to a base::TimeTicks value. The conversion isn't
-// exact, but is within the time delta taken to synchronously resolve
-// base::Time::Now() and base::TimeTicks::Now() which in practice is pretty
-// much instant compared to multi-seconds startup timings.
-// TODO(gab): Find a precise way to do this (http://crbug.com/544131).
+// exact, but by capturing Time::Now() as early as possible, the likelihood of a
+// clock change between it and process start is as low as possible. There is
+// also the time taken to synchronously resolve base::Time::Now() and
+// base::TimeTicks::Now() at play, but in practice it is pretty much instant
+// compared to multi-seconds startup timings.
base::TimeTicks StartupTimeToTimeTicks(const base::Time& time) {
// First get a base which represents the same point in time in both units.
- // The wall clock time it takes to gather both of these is the precision of
- // this method.
+ // Bump the priority of this thread while doing this as the wall clock time it
+ // takes to resolve these two calls affects the precision of this method and
+ // bumping the priority reduces the likelihood of a context switch interfering
+ // with this computation.
+
+// platform_thread_mac.mm unfortunately doesn't properly support base's
+// thread priority APIs (crbug.com/554651).
+#if !defined(OS_MACOSX)
+ static bool statics_initialized = false;
grt (UTC plus 2) 2016/09/17 09:22:06 Hi gang. The call to RecordExeMainEntryPointTime f
fdoray 2016/09/19 13:14:46 RecordStartupProcessCreationTime() takes a base::T
+
+ base::ThreadPriority previous_priority = base::ThreadPriority::NORMAL;
+ if (!statics_initialized) {
+ previous_priority = base::PlatformThread::GetCurrentThreadPriority();
+ base::PlatformThread::SetCurrentThreadPriority(
+ base::ThreadPriority::DISPLAY);
+ }
+#endif
+
static const base::Time time_base = base::Time::Now();
static const base::TimeTicks trace_ticks_base = base::TimeTicks::Now();
+#if !defined(OS_MACOSX)
+ if (!statics_initialized) {
+ base::PlatformThread::SetCurrentThreadPriority(previous_priority);
+ }
+
+ statics_initialized = true;
+#endif
+
// Then use the TimeDelta common ground between the two units to make the
// conversion.
const base::TimeDelta delta_since_base = time_base - time;
@@ -269,17 +299,17 @@ void RecordMainEntryTimeHistogram() {
const int kLowWordMask = 0xFFFFFFFF;
const int kLower31BitsMask = 0x7FFFFFFF;
DCHECK(!g_main_entry_point_time.Get().is_null());
- base::TimeDelta browser_main_entry_time_absolute =
+ const base::TimeDelta browser_main_entry_time_absolute =
g_main_entry_point_time.Get() - base::Time::UnixEpoch();
- uint64 browser_main_entry_time_raw_ms =
+ const uint64 browser_main_entry_time_raw_ms =
browser_main_entry_time_absolute.InMilliseconds();
- base::TimeDelta browser_main_entry_time_raw_ms_high_word =
+ const base::TimeDelta browser_main_entry_time_raw_ms_high_word =
base::TimeDelta::FromMilliseconds(
(browser_main_entry_time_raw_ms >> 32) & kLowWordMask);
// Shift by one because histograms only support non-negative values.
- base::TimeDelta browser_main_entry_time_raw_ms_low_word =
+ const base::TimeDelta browser_main_entry_time_raw_ms_low_word =
base::TimeDelta::FromMilliseconds(
(browser_main_entry_time_raw_ms >> 1) & kLower31BitsMask);
@@ -291,19 +321,20 @@ void RecordMainEntryTimeHistogram() {
}
// Environment variable that stores the timestamp when the executable's main()
-// function was entered.
-const char kChromeMainTimeEnvVar[] = "CHROME_MAIN_TIME";
+// function was entered in TimeTicks. This is required because chrome.exe and
+// chrome.dll don't share the same static storage.
+const char kChromeMainTicksEnvVar[] = "CHROME_MAIN_TICKS";
// Returns the time of main entry recorded from RecordExeMainEntryTime.
-base::Time ExeMainEntryPointTime() {
+base::TimeTicks ExeMainEntryPointTicks() {
scoped_ptr<base::Environment> env(base::Environment::Create());
- std::string time_string;
+ std::string ticks_string;
int64 time_int = 0;
- if (env->GetVar(kChromeMainTimeEnvVar, &time_string) &&
- base::StringToInt64(time_string, &time_int)) {
- return base::Time::FromInternalValue(time_int);
+ if (env->GetVar(kChromeMainTicksEnvVar, &ticks_string) &&
+ base::StringToInt64(ticks_string, &time_int)) {
+ return base::TimeTicks::FromInternalValue(time_int);
}
- return base::Time();
+ return base::TimeTicks();
}
} // namespace
@@ -317,33 +348,41 @@ void SetNonBrowserUIDisplayed() {
}
void RecordStartupProcessCreationTime(const base::Time& time) {
- DCHECK(g_process_creation_time.Get().is_null());
- g_process_creation_time.Get() = time;
- DCHECK(!g_process_creation_time.Get().is_null());
+ DCHECK(g_process_creation_ticks.Get().is_null());
+ g_process_creation_ticks.Get() = StartupTimeToTimeTicks(time);
+ DCHECK(!g_process_creation_ticks.Get().is_null());
}
void RecordMainEntryPointTime(const base::Time& time) {
+ DCHECK(g_main_entry_point_ticks.Get().is_null());
+ g_main_entry_point_ticks.Get() = StartupTimeToTimeTicks(time);
+ DCHECK(!g_main_entry_point_ticks.Get().is_null());
+
+ // TODO(jeremy): Remove this with RecordMainEntryTimeHistogram() when
+ // resolving crbug.com/317481.
DCHECK(g_main_entry_point_time.Get().is_null());
g_main_entry_point_time.Get() = time;
DCHECK(!g_main_entry_point_time.Get().is_null());
}
void RecordExeMainEntryPointTime(const base::Time& time) {
- std::string exe_load_time = base::Int64ToString(time.ToInternalValue());
+ const std::string exe_load_ticks =
+ base::Int64ToString(StartupTimeToTimeTicks(time).ToInternalValue());
scoped_ptr<base::Environment> env(base::Environment::Create());
- env->SetVar(kChromeMainTimeEnvVar, exe_load_time);
+ env->SetVar(kChromeMainTicksEnvVar, exe_load_ticks);
}
-void RecordBrowserMainMessageLoopStart(const base::Time& time,
+void RecordBrowserMainMessageLoopStart(const base::TimeTicks& ticks,
bool is_first_run) {
RecordHardFaultHistogram(is_first_run);
RecordMainEntryTimeHistogram();
- const base::Time& process_creation_time = g_process_creation_time.Get();
- if (!is_first_run && !process_creation_time.is_null()) {
+ const base::TimeTicks& process_creation_ticks =
+ g_process_creation_ticks.Get();
+ if (!is_first_run && !process_creation_ticks.is_null()) {
UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
UMA_HISTOGRAM_LONG_TIMES_100, "Startup.BrowserMessageLoopStartTime",
- process_creation_time, time);
+ process_creation_ticks, ticks);
}
// Bail if uptime < 7 minutes, to filter out cases where Chrome may have been
@@ -361,49 +400,49 @@ void RecordBrowserMainMessageLoopStart(const base::Time& time,
UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
UMA_HISTOGRAM_LONG_TIMES,
"Startup.BrowserMessageLoopStartTimeFromMainEntry.FirstRun",
- g_main_entry_point_time.Get(), time);
+ g_main_entry_point_ticks.Get(), ticks);
} else {
UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
UMA_HISTOGRAM_LONG_TIMES,
"Startup.BrowserMessageLoopStartTimeFromMainEntry",
- g_main_entry_point_time.Get(), time);
+ g_main_entry_point_ticks.Get(), ticks);
}
// Record timings between process creation, the main() in the executable being
// reached and the main() in the shared library being reached.
- if (!process_creation_time.is_null()) {
- const base::Time exe_main_time = ExeMainEntryPointTime();
- if (!exe_main_time.is_null()) {
+ if (!process_creation_ticks.is_null()) {
+ const base::TimeTicks exe_main_ticks = ExeMainEntryPointTicks();
+ if (!exe_main_ticks.is_null()) {
// Process create to chrome.exe:main().
UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ProcessCreateToExeMain",
- process_creation_time, exe_main_time);
+ process_creation_ticks, exe_main_ticks);
// chrome.exe:main() to chrome.dll:main().
UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ExeMainToDllMain",
- exe_main_time, g_main_entry_point_time.Get());
+ exe_main_ticks, g_main_entry_point_ticks.Get());
// Process create to chrome.dll:main(). Reported as a histogram only as
// the other two events above are sufficient for tracing purposes.
UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(
UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ProcessCreateToDllMain",
- g_main_entry_point_time.Get() - process_creation_time);
+ g_main_entry_point_ticks.Get() - process_creation_ticks);
}
}
}
-void RecordBrowserWindowDisplay(const base::Time& time) {
+void RecordBrowserWindowDisplay(const base::TimeTicks& ticks) {
static bool is_first_call = true;
- if (!is_first_call || time.is_null())
+ if (!is_first_call || ticks.is_null())
return;
is_first_call = false;
- if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null())
+ if (WasNonBrowserUIDisplayed() || g_process_creation_ticks.Get().is_null())
return;
UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
UMA_HISTOGRAM_LONG_TIMES, "Startup.BrowserWindowDisplay",
- g_process_creation_time.Get(), time);
+ g_process_creation_ticks.Get(), ticks);
}
void RecordBrowserOpenTabsDelta(const base::TimeDelta& delta) {
@@ -416,88 +455,91 @@ void RecordBrowserOpenTabsDelta(const base::TimeDelta& delta) {
"Startup.BrowserOpenTabs", delta);
}
-void RecordFirstWebContentsMainFrameLoad(const base::Time& time) {
+void RecordFirstWebContentsMainFrameLoad(const base::TimeTicks& ticks) {
static bool is_first_call = true;
- if (!is_first_call || time.is_null())
+ if (!is_first_call || ticks.is_null())
return;
is_first_call = false;
- if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null())
+ if (WasNonBrowserUIDisplayed() || g_process_creation_ticks.Get().is_null())
return;
UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.MainFrameLoad2",
- g_process_creation_time.Get(), time);
+ g_process_creation_ticks.Get(), ticks);
}
-void RecordDeprecatedFirstWebContentsMainFrameLoad(const base::Time& time) {
+void RecordDeprecatedFirstWebContentsMainFrameLoad(
+ const base::TimeTicks& ticks) {
static bool is_first_call = true;
- if (!is_first_call || time.is_null())
+ if (!is_first_call || ticks.is_null())
return;
is_first_call = false;
- if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null())
+ if (WasNonBrowserUIDisplayed() || g_process_creation_ticks.Get().is_null())
return;
UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(
UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.MainFrameLoad",
- time - g_process_creation_time.Get());
+ ticks - g_process_creation_ticks.Get());
}
-void RecordFirstWebContentsNonEmptyPaint(const base::Time& time) {
+void RecordFirstWebContentsNonEmptyPaint(const base::TimeTicks& ticks) {
static bool is_first_call = true;
- if (!is_first_call || time.is_null())
+ if (!is_first_call || ticks.is_null())
return;
is_first_call = false;
- if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null())
+ if (WasNonBrowserUIDisplayed() || g_process_creation_ticks.Get().is_null())
return;
UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.NonEmptyPaint2",
- g_process_creation_time.Get(), time);
+ g_process_creation_ticks.Get(), ticks);
}
-void RecordDeprecatedFirstWebContentsNonEmptyPaint(const base::Time& time) {
+void RecordDeprecatedFirstWebContentsNonEmptyPaint(
+ const base::TimeTicks& ticks) {
static bool is_first_call = true;
- if (!is_first_call || time.is_null())
+ if (!is_first_call || ticks.is_null())
return;
is_first_call = false;
- if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null())
+ if (WasNonBrowserUIDisplayed() || g_process_creation_ticks.Get().is_null())
return;
UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(
UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.NonEmptyPaint",
- time - g_process_creation_time.Get());
+ ticks - g_process_creation_ticks.Get());
}
-void RecordFirstWebContentsMainNavigationStart(const base::Time& time) {
+void RecordFirstWebContentsMainNavigationStart(const base::TimeTicks& ticks) {
static bool is_first_call = true;
- if (!is_first_call || time.is_null())
+ if (!is_first_call || ticks.is_null())
return;
is_first_call = false;
- if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null())
+ if (WasNonBrowserUIDisplayed() || g_process_creation_ticks.Get().is_null())
return;
UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
UMA_HISTOGRAM_LONG_TIMES_100,
"Startup.FirstWebContents.MainNavigationStart",
- g_process_creation_time.Get(), time);
+ g_process_creation_ticks.Get(), ticks);
}
-void RecordFirstWebContentsMainNavigationFinished(const base::Time& time) {
+void RecordFirstWebContentsMainNavigationFinished(
+ const base::TimeTicks& ticks) {
static bool is_first_call = true;
- if (!is_first_call || time.is_null())
+ if (!is_first_call || ticks.is_null())
return;
is_first_call = false;
- if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null())
+ if (WasNonBrowserUIDisplayed() || g_process_creation_ticks.Get().is_null())
return;
UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
UMA_HISTOGRAM_LONG_TIMES_100,
"Startup.FirstWebContents.MainNavigationFinished",
- g_process_creation_time.Get(), time);
+ g_process_creation_ticks.Get(), ticks);
}
-base::Time MainEntryPointTime() {
- return g_main_entry_point_time.Get();
+base::TimeTicks MainEntryPointTicks() {
+ return g_main_entry_point_ticks.Get();
}
StartupTemperature GetStartupTemperature() {
« no previous file with comments | « components/startup_metric_utils/browser/startup_metric_utils.h ('k') | mandoline/ui/desktop_ui/browser_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698