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

Side by Side Diff: components/startup_metric_utils/startup_metric_utils.cc

Issue 1408483002: Add top-level async trace events for the main startup timings. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 months 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 unified diff | Download patch
« no previous file with comments | « base/trace_event/trace_event_common.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "components/startup_metric_utils/startup_metric_utils.h" 5 #include "components/startup_metric_utils/startup_metric_utils.h"
6 6
7 #include "base/containers/hash_tables.h" 7 #include "base/containers/hash_tables.h"
8 #include "base/environment.h" 8 #include "base/environment.h"
9 #include "base/lazy_instance.h" 9 #include "base/lazy_instance.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/metrics/histogram_macros.h" 11 #include "base/metrics/histogram_macros.h"
12 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/sys_info.h" 13 #include "base/sys_info.h"
14 #include "base/trace_event/trace_event.h"
14 15
15 #if defined(OS_WIN) 16 #if defined(OS_WIN)
16 #include <winternl.h> 17 #include <winternl.h>
17 #include "base/win/windows_version.h" 18 #include "base/win/windows_version.h"
18 #endif 19 #endif
19 20
20 namespace startup_metric_utils { 21 namespace startup_metric_utils {
21 22
22 namespace { 23 namespace {
23 24
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 // Helper macro for splitting out an UMA histogram based on cold or warm start. 156 // Helper macro for splitting out an UMA histogram based on cold or warm start.
156 // |type| is the histogram type, and corresponds to an UMA macro like 157 // |type| is the histogram type, and corresponds to an UMA macro like
157 // UMA_HISTOGRAM_LONG_TIMES. It must be itself be a macro that only takes two 158 // UMA_HISTOGRAM_LONG_TIMES. It must be itself be a macro that only takes two
158 // parameters. 159 // parameters.
159 // |basename| is the basename of the histogram. A histogram of this name will 160 // |basename| is the basename of the histogram. A histogram of this name will
160 // always be recorded to. If the startup is either cold or warm then a value 161 // always be recorded to. If the startup is either cold or warm then a value
161 // will also be recorded to the histogram with name |basename| and suffix 162 // will also be recorded to the histogram with name |basename| and suffix
162 // ".ColdStart" or ".WarmStart", as appropriate. 163 // ".ColdStart" or ".WarmStart", as appropriate.
163 // |value_expr| is an expression evaluating to the value to be recorded. This 164 // |value_expr| is an expression evaluating to the value to be recorded. This
164 // will be evaluated exactly once and cached, so side effects are not an issue. 165 // will be evaluated exactly once and cached, so side effects are not an issue.
165 #define UMA_HISTOGRAM_BY_STARTUP_TEMPERATURE(type, basename, value_expr) { \ 166 #define UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(type, basename, value_expr) \
166 const auto kValue = value_expr; \ 167 { \
167 /* Always record to the base histogram. */ \ 168 const auto kValue = value_expr; \
168 type(basename, kValue); \ 169 /* Always record to the base histogram. */ \
169 /* Record to the cold/warm suffixed histogram as appropriate. */ \ 170 type(basename, kValue); \
170 if (g_startup_temperature == COLD_STARTUP_TEMPERATURE) { \ 171 /* Record to the cold/warm suffixed histogram as appropriate. */ \
171 type(basename ".ColdStartup", kValue); \ 172 if (g_startup_temperature == COLD_STARTUP_TEMPERATURE) { \
172 } else if (g_startup_temperature == WARM_STARTUP_TEMPERATURE) { \ 173 type(basename ".ColdStartup", kValue); \
173 type(basename ".WarmStartup", kValue); \ 174 } else if (g_startup_temperature == WARM_STARTUP_TEMPERATURE) { \
174 } \ 175 type(basename ".WarmStartup", kValue); \
175 } 176 } \
177 }
176 178
179 #define UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(type, basename, \
180 begin_time, end_time) \
181 { \
182 UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(type, basename, \
183 end_time - begin_time) \
184 TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( \
185 "startup", basename, 0, \
186 StartupTimeToTraceTicks(begin_time).ToInternalValue(), "Temperature", \
187 g_startup_temperature); \
188 TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP1( \
189 "startup", basename, 0, \
190 StartupTimeToTraceTicks(end_time).ToInternalValue(), "Temperature", \
191 g_startup_temperature); \
192 }
177 193
178 // On Windows, records the number of hard-faults that have occurred in the 194 // On Windows, records the number of hard-faults that have occurred in the
179 // current chrome.exe process since it was started. This is a nop on other 195 // current chrome.exe process since it was started. This is a nop on other
180 // platforms. 196 // platforms.
181 // crbug.com/476923 197 // crbug.com/476923
182 // TODO(chrisha): If this proves useful, use it to split startup stats in two. 198 // TODO(chrisha): If this proves useful, use it to split startup stats in two.
183 void RecordHardFaultHistogram(bool is_first_run) { 199 void RecordHardFaultHistogram(bool is_first_run) {
184 #if defined(OS_WIN) 200 #if defined(OS_WIN)
185 uint32_t hard_fault_count = 0; 201 uint32_t hard_fault_count = 0;
186 bool has_os_support = false; 202 bool has_os_support = false;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 } else if (hard_fault_count >= COLD_START_HARD_FAULT_COUNT_THRESHOLD) { 238 } else if (hard_fault_count >= COLD_START_HARD_FAULT_COUNT_THRESHOLD) {
223 g_startup_temperature = COLD_STARTUP_TEMPERATURE; 239 g_startup_temperature = COLD_STARTUP_TEMPERATURE;
224 } 240 }
225 241
226 // Record the startup 'temperature'. 242 // Record the startup 'temperature'.
227 UMA_HISTOGRAM_ENUMERATION( 243 UMA_HISTOGRAM_ENUMERATION(
228 "Startup.Temperature", g_startup_temperature, STARTUP_TEMPERATURE_MAX); 244 "Startup.Temperature", g_startup_temperature, STARTUP_TEMPERATURE_MAX);
229 #endif // defined(OS_WIN) 245 #endif // defined(OS_WIN)
230 } 246 }
231 247
248 // Converts a base::Time value to a base::TraceTicks value. The conversion isn't
249 // exact, but is within the time delta taken to synchronously resolve
250 // base::Time::Now() and base::TraceTicks::Now() which in practice is pretty
251 // much instant compared to multi-seconds startup timings.
252 base::TraceTicks StartupTimeToTraceTicks(const base::Time& time) {
253 // First get a base which represents the same point in time in both units.
254 // The wall clock time it takes to gather both of these is the precision of
255 // this method.
256 static const base::Time time_base = base::Time::Now();
257 static const base::TraceTicks trace_ticks_base = base::TraceTicks::Now();
258
259 // Then use the TimeDelta common ground between the two units to make the
260 // conversion.
261 const base::TimeDelta delta_since_base = time_base - time;
nduca 2015/10/16 00:22:48 actually, now that i look at this, my lg is only c
gab 2015/10/16 14:39:16 Not sure I understand what you mean here?
262 return trace_ticks_base - delta_since_base;
263 }
264
232 // Record time of main entry so it can be read from Telemetry performance tests. 265 // Record time of main entry so it can be read from Telemetry performance tests.
233 // TODO(jeremy): Remove once crbug.com/317481 is fixed. 266 // TODO(jeremy): Remove once crbug.com/317481 is fixed.
234 void RecordMainEntryTimeHistogram() { 267 void RecordMainEntryTimeHistogram() {
235 const int kLowWordMask = 0xFFFFFFFF; 268 const int kLowWordMask = 0xFFFFFFFF;
236 const int kLower31BitsMask = 0x7FFFFFFF; 269 const int kLower31BitsMask = 0x7FFFFFFF;
237 DCHECK(!MainEntryPointTime().is_null()); 270 DCHECK(!MainEntryPointTime().is_null());
238 base::TimeDelta browser_main_entry_time_absolute = 271 base::TimeDelta browser_main_entry_time_absolute =
239 MainEntryPointTime() - base::Time::UnixEpoch(); 272 MainEntryPointTime() - base::Time::UnixEpoch();
240 273
241 uint64 browser_main_entry_time_raw_ms = 274 uint64 browser_main_entry_time_raw_ms =
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 env->SetVar(kChromeMainTimeEnvVar, exe_load_time); 333 env->SetVar(kChromeMainTimeEnvVar, exe_load_time);
301 } 334 }
302 335
303 void RecordBrowserMainMessageLoopStart(const base::Time& time, 336 void RecordBrowserMainMessageLoopStart(const base::Time& time,
304 bool is_first_run) { 337 bool is_first_run) {
305 RecordHardFaultHistogram(is_first_run); 338 RecordHardFaultHistogram(is_first_run);
306 RecordMainEntryTimeHistogram(); 339 RecordMainEntryTimeHistogram();
307 340
308 const base::Time& process_creation_time = g_process_creation_time.Get(); 341 const base::Time& process_creation_time = g_process_creation_time.Get();
309 if (!is_first_run && !process_creation_time.is_null()) { 342 if (!is_first_run && !process_creation_time.is_null()) {
310 UMA_HISTOGRAM_BY_STARTUP_TEMPERATURE( 343 UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
311 UMA_HISTOGRAM_LONG_TIMES_100, 344 UMA_HISTOGRAM_LONG_TIMES_100, "Startup.BrowserMessageLoopStartTime",
312 "Startup.BrowserMessageLoopStartTime", 345 process_creation_time, time);
313 time - process_creation_time);
314 } 346 }
315 347
316 // Bail if uptime < 7 minutes, to filter out cases where Chrome may have been 348 // Bail if uptime < 7 minutes, to filter out cases where Chrome may have been
317 // autostarted and the machine is under io pressure. 349 // autostarted and the machine is under io pressure.
318 const int64 kSevenMinutesInMilliseconds = 350 const int64 kSevenMinutesInMilliseconds =
319 base::TimeDelta::FromMinutes(7).InMilliseconds(); 351 base::TimeDelta::FromMinutes(7).InMilliseconds();
320 if (base::SysInfo::Uptime() < kSevenMinutesInMilliseconds) 352 if (base::SysInfo::Uptime() < kSevenMinutesInMilliseconds)
321 return; 353 return;
322 354
323 // The Startup.BrowserMessageLoopStartTime histogram exhibits instability in 355 // The Startup.BrowserMessageLoopStartTime histogram exhibits instability in
324 // the field which limits its usefulness in all scenarios except when we have 356 // the field which limits its usefulness in all scenarios except when we have
325 // a very large sample size. Attempt to mitigate this with a new metric: 357 // a very large sample size. Attempt to mitigate this with a new metric:
326 // * Measure time from main entry rather than the OS' notion of process start. 358 // * Measure time from main entry rather than the OS' notion of process start.
327 // * Only measure launches that occur 7 minutes after boot to try to avoid 359 // * Only measure launches that occur 7 minutes after boot to try to avoid
328 // cases where Chrome is auto-started and IO is heavily loaded. 360 // cases where Chrome is auto-started and IO is heavily loaded.
329 const base::Time dll_main_time = MainEntryPointTime(); 361 const base::Time dll_main_time = MainEntryPointTime();
330 base::TimeDelta startup_time_from_main_entry = time - dll_main_time;
331 if (is_first_run) { 362 if (is_first_run) {
332 UMA_HISTOGRAM_BY_STARTUP_TEMPERATURE( 363 UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
333 UMA_HISTOGRAM_LONG_TIMES, 364 UMA_HISTOGRAM_LONG_TIMES,
334 "Startup.BrowserMessageLoopStartTimeFromMainEntry.FirstRun", 365 "Startup.BrowserMessageLoopStartTimeFromMainEntry.FirstRun",
335 startup_time_from_main_entry); 366 dll_main_time, time);
336 } else { 367 } else {
337 UMA_HISTOGRAM_BY_STARTUP_TEMPERATURE( 368 UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
338 UMA_HISTOGRAM_LONG_TIMES, 369 UMA_HISTOGRAM_LONG_TIMES,
339 "Startup.BrowserMessageLoopStartTimeFromMainEntry", 370 "Startup.BrowserMessageLoopStartTimeFromMainEntry", dll_main_time,
340 startup_time_from_main_entry); 371 time);
341 } 372 }
342 373
343 // Record timings between process creation, the main() in the executable being 374 // Record timings between process creation, the main() in the executable being
344 // reached and the main() in the shared library being reached. 375 // reached and the main() in the shared library being reached.
345 if (!process_creation_time.is_null()) { 376 if (!process_creation_time.is_null()) {
346 const base::Time exe_main_time = ExeMainEntryPointTime(); 377 const base::Time exe_main_time = ExeMainEntryPointTime();
347 if (!exe_main_time.is_null()) { 378 if (!exe_main_time.is_null()) {
348 // Process create to chrome.exe:main(). 379 // Process create to chrome.exe:main().
349 UMA_HISTOGRAM_BY_STARTUP_TEMPERATURE( 380 UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
350 UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ProcessCreateToExeMain", 381 UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ProcessCreateToExeMain",
351 exe_main_time - process_creation_time); 382 process_creation_time, exe_main_time);
352 383
353 // chrome.exe:main() to chrome.dll:main(). 384 // chrome.exe:main() to chrome.dll:main().
354 UMA_HISTOGRAM_BY_STARTUP_TEMPERATURE( 385 UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
355 UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ExeMainToDllMain", 386 UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ExeMainToDllMain",
356 dll_main_time - exe_main_time); 387 exe_main_time, dll_main_time);
357 388
358 // Process create to chrome.dll:main(). 389 // Process create to chrome.dll:main(). Reported as a histogram only as
359 UMA_HISTOGRAM_BY_STARTUP_TEMPERATURE( 390 // the other two events above are sufficient for tracing purposes.
391 UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(
360 UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ProcessCreateToDllMain", 392 UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ProcessCreateToDllMain",
361 dll_main_time - process_creation_time); 393 dll_main_time - process_creation_time);
362 } 394 }
363 } 395 }
364 } 396 }
365 397
366 void RecordBrowserWindowDisplay(const base::Time& time) { 398 void RecordBrowserWindowDisplay(const base::Time& time) {
367 static bool is_first_call = true; 399 static bool is_first_call = true;
368 if (!is_first_call || time.is_null()) 400 if (!is_first_call || time.is_null())
369 return; 401 return;
370 is_first_call = false; 402 is_first_call = false;
371 if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) 403 if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null())
372 return; 404 return;
373 405
374 UMA_HISTOGRAM_BY_STARTUP_TEMPERATURE( 406 UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
375 UMA_HISTOGRAM_LONG_TIMES, "Startup.BrowserWindowDisplay", 407 UMA_HISTOGRAM_LONG_TIMES, "Startup.BrowserWindowDisplay",
376 time - g_process_creation_time.Get()); 408 g_process_creation_time.Get(), time);
377 } 409 }
378 410
379 void RecordBrowserOpenTabsDelta(const base::TimeDelta& delta) { 411 void RecordBrowserOpenTabsDelta(const base::TimeDelta& delta) {
380 static bool is_first_call = true; 412 static bool is_first_call = true;
381 if (!is_first_call) 413 if (!is_first_call)
382 return; 414 return;
383 is_first_call = false; 415 is_first_call = false;
384 416
385 UMA_HISTOGRAM_BY_STARTUP_TEMPERATURE( 417 UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(UMA_HISTOGRAM_LONG_TIMES_100,
386 UMA_HISTOGRAM_LONG_TIMES_100, "Startup.BrowserOpenTabs", delta); 418 "Startup.BrowserOpenTabs", delta);
387 } 419 }
388 420
389 void RecordFirstWebContentsMainFrameLoad(const base::Time& time) { 421 void RecordFirstWebContentsMainFrameLoad(const base::Time& time) {
390 static bool is_first_call = true; 422 static bool is_first_call = true;
391 if (!is_first_call || time.is_null()) 423 if (!is_first_call || time.is_null())
392 return; 424 return;
393 is_first_call = false; 425 is_first_call = false;
394 if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) 426 if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null())
395 return; 427 return;
396 428
397 UMA_HISTOGRAM_BY_STARTUP_TEMPERATURE( 429 UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
398 UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.MainFrameLoad", 430 UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.MainFrameLoad",
399 time - g_process_creation_time.Get()); 431 g_process_creation_time.Get(), time);
400 } 432 }
401 433
402 void RecordFirstWebContentsNonEmptyPaint(const base::Time& time) { 434 void RecordFirstWebContentsNonEmptyPaint(const base::Time& time) {
403 static bool is_first_call = true; 435 static bool is_first_call = true;
404 if (!is_first_call || time.is_null()) 436 if (!is_first_call || time.is_null())
405 return; 437 return;
406 is_first_call = false; 438 is_first_call = false;
407 if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null()) 439 if (WasNonBrowserUIDisplayed() || g_process_creation_time.Get().is_null())
408 return; 440 return;
409 441
410 UMA_HISTOGRAM_BY_STARTUP_TEMPERATURE( 442 UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
411 UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.NonEmptyPaint", 443 UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.NonEmptyPaint",
412 time - g_process_creation_time.Get()); 444 g_process_creation_time.Get(), time);
413 } 445 }
414 446
415 base::Time MainEntryPointTime() { 447 base::Time MainEntryPointTime() {
416 return g_main_entry_point_time.Get(); 448 return g_main_entry_point_time.Get();
417 } 449 }
418 450
419 StartupTemperature GetStartupTemperature() { 451 StartupTemperature GetStartupTemperature() {
420 return g_startup_temperature; 452 return g_startup_temperature;
421 } 453 }
422 454
423 } // namespace startup_metric_utils 455 } // namespace startup_metric_utils
OLDNEW
« no previous file with comments | « base/trace_event/trace_event_common.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698