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

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

Issue 1663853003: [Merge M48] "[Merge M49] Add SameVersionStartupCounts suffix to startup HardFault and Temperature h… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@merge_m48_b2_startupVcount
Patch Set: Created 4 years, 10 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
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/browser/startup_metric_utils.h" 5 #include "components/startup_metric_utils/browser/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.h"
11 #include "base/metrics/histogram_macros.h" 12 #include "base/metrics/histogram_macros.h"
12 #include "base/prefs/pref_registry_simple.h" 13 #include "base/prefs/pref_registry_simple.h"
13 #include "base/prefs/pref_service.h" 14 #include "base/prefs/pref_service.h"
14 #include "base/process/process_info.h" 15 #include "base/process/process_info.h"
15 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
16 #include "base/sys_info.h" 17 #include "base/sys_info.h"
17 #include "base/threading/platform_thread.h" 18 #include "base/threading/platform_thread.h"
18 #include "base/trace_event/trace_event.h" 19 #include "base/trace_event/trace_event.h"
19 #include "build/build_config.h" 20 #include "build/build_config.h"
20 #include "components/startup_metric_utils/browser/pref_names.h" 21 #include "components/startup_metric_utils/browser/pref_names.h"
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 GetSystemUptimeOnProcessLaunch(); 239 GetSystemUptimeOnProcessLaunch();
239 if (system_uptime_on_process_launch.is_zero()) 240 if (system_uptime_on_process_launch.is_zero())
240 return; 241 return;
241 242
242 UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(UMA_HISTOGRAM_LONG_TIMES_100, 243 UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(UMA_HISTOGRAM_LONG_TIMES_100,
243 "Startup.SystemUptime", 244 "Startup.SystemUptime",
244 GetSystemUptimeOnProcessLaunch()); 245 GetSystemUptimeOnProcessLaunch());
245 } 246 }
246 247
247 // On Windows, records the number of hard-faults that have occurred in the 248 // On Windows, records the number of hard-faults that have occurred in the
248 // current chrome.exe process since it was started. This is a nop on other 249 // current chrome.exe process since it was started. A version of the histograms
249 // platforms. 250 // recorded in this method suffixed by |same_version_startup_count| will also be
250 void RecordHardFaultHistogram(bool is_first_run) { 251 // recorded (unless |same_version_startup_count| is 0 which indicates it's
252 // unknown). This is a nop on other platforms.
253 void RecordHardFaultHistogram(int same_version_startup_count) {
251 #if defined(OS_WIN) 254 #if defined(OS_WIN)
252 uint32_t hard_fault_count = 0; 255 uint32_t hard_fault_count = 0;
253 bool has_os_support = false; 256 bool has_os_support = false;
254 bool success = GetHardFaultCountForCurrentProcess( 257 bool success = GetHardFaultCountForCurrentProcess(
255 &hard_fault_count, &has_os_support); 258 &hard_fault_count, &has_os_support);
256 259
257 // Log whether or not the system call was successful, assuming the OS was 260 // Log whether or not the system call was successful, assuming the OS was
258 // detected to support it. 261 // detected to support it.
259 if (has_os_support) { 262 if (has_os_support) {
260 UMA_HISTOGRAM_BOOLEAN( 263 UMA_HISTOGRAM_BOOLEAN(
261 "Startup.BrowserMessageLoopStartHardFaultCount.Success", 264 "Startup.BrowserMessageLoopStartHardFaultCount.Success",
262 success); 265 success);
263 } 266 }
264 267
265 // Don't log a histogram value if unable to get the hard fault count. 268 // Don't record histograms if unable to get the hard fault count.
266 if (!success) 269 if (!success)
267 return; 270 return;
268 271
272 std::string same_version_startup_count_suffix;
273 if (same_version_startup_count != 0) {
274 // Histograms below will be suffixed by |same_version_startup_count| up to
275 // |kMaxSameVersionCountRecorded|, higher counts will be grouped in the
276 // ".Over" suffix. Make sure to reflect changes to
277 // kMaxSameVersionCountRecorded in the "SameVersionStartupCounts" histogram
278 // suffix.
279 const int kMaxSameVersionCountRecorded = 9;
280 same_version_startup_count_suffix.push_back('.');
281 DCHECK_GE(same_version_startup_count, 1);
282 if (same_version_startup_count <= kMaxSameVersionCountRecorded) {
283 same_version_startup_count_suffix.append(
284 base::IntToString(same_version_startup_count));
285 } else {
286 same_version_startup_count_suffix.append("Over");
287 }
288 }
289
269 // Hard fault counts are expected to be in the thousands range, 290 // Hard fault counts are expected to be in the thousands range,
270 // corresponding to faulting in ~10s of MBs of code ~10s of KBs at a time. 291 // corresponding to faulting in ~10s of MBs of code ~10s of KBs at a time.
271 // (Observed to vary from 1000 to 10000 on various test machines and 292 // (Observed to vary from 1000 to 10000 on various test machines and
272 // platforms.) 293 // platforms.)
273 if (is_first_run) { 294 const char kHardFaultCountHistogram[] =
274 UMA_HISTOGRAM_CUSTOM_COUNTS( 295 "Startup.BrowserMessageLoopStartHardFaultCount";
275 "Startup.BrowserMessageLoopStartHardFaultCount.FirstRun", 296 UMA_HISTOGRAM_CUSTOM_COUNTS(kHardFaultCountHistogram, hard_fault_count, 1,
276 hard_fault_count, 297 40000, 50);
277 0, 40000, 50); 298 // Also record the hard fault count histogram suffixed by the number of
278 } else { 299 // startups this specific version has been through.
279 UMA_HISTOGRAM_CUSTOM_COUNTS( 300 // Factory properties copied from UMA_HISTOGRAM_CUSTOM_COUNTS macro.
280 "Startup.BrowserMessageLoopStartHardFaultCount", 301 if (!same_version_startup_count_suffix.empty()) {
281 hard_fault_count, 302 base::Histogram::FactoryGet(
282 0, 40000, 50); 303 kHardFaultCountHistogram + same_version_startup_count_suffix, 1, 40000,
304 50, base::HistogramBase::kUmaTargetedHistogramFlag)
305 ->Add(hard_fault_count);
283 } 306 }
284 307
285 // Determine the startup type based on the number of observed hard faults. 308 // Determine the startup type based on the number of observed hard faults.
286 DCHECK_EQ(UNDETERMINED_STARTUP_TEMPERATURE, g_startup_temperature); 309 DCHECK_EQ(UNDETERMINED_STARTUP_TEMPERATURE, g_startup_temperature);
287 if (hard_fault_count < WARM_START_HARD_FAULT_COUNT_THRESHOLD) { 310 if (hard_fault_count < WARM_START_HARD_FAULT_COUNT_THRESHOLD) {
288 g_startup_temperature = WARM_STARTUP_TEMPERATURE; 311 g_startup_temperature = WARM_STARTUP_TEMPERATURE;
289 } else if (hard_fault_count >= COLD_START_HARD_FAULT_COUNT_THRESHOLD) { 312 } else if (hard_fault_count >= COLD_START_HARD_FAULT_COUNT_THRESHOLD) {
290 g_startup_temperature = COLD_STARTUP_TEMPERATURE; 313 g_startup_temperature = COLD_STARTUP_TEMPERATURE;
291 } else { 314 } else {
292 g_startup_temperature = LUKEWARM_STARTUP_TEMPERATURE; 315 g_startup_temperature = LUKEWARM_STARTUP_TEMPERATURE;
293 } 316 }
294 317
295 // Record the startup 'temperature'. 318 // Record the startup 'temperature'.
296 UMA_HISTOGRAM_ENUMERATION( 319 const char kStartupTemperatureHistogram[] = "Startup.Temperature";
297 "Startup.Temperature", g_startup_temperature, STARTUP_TEMPERATURE_COUNT); 320 UMA_HISTOGRAM_ENUMERATION(kStartupTemperatureHistogram, g_startup_temperature,
321 STARTUP_TEMPERATURE_COUNT);
322 // As well as its suffixed twin.
323 // Factory properties copied from UMA_HISTOGRAM_ENUMERATION macro.
324 if (!same_version_startup_count_suffix.empty()) {
325 base::LinearHistogram::FactoryGet(
326 kStartupTemperatureHistogram + same_version_startup_count_suffix, 1,
327 STARTUP_TEMPERATURE_COUNT, STARTUP_TEMPERATURE_COUNT + 1,
328 base::HistogramBase::kUmaTargetedHistogramFlag)
329 ->Add(g_startup_temperature);
330 }
298 #endif // defined(OS_WIN) 331 #endif // defined(OS_WIN)
299 } 332 }
300 333
301 // Converts a base::Time value to a base::TimeTicks value. The conversion isn't 334 // Converts a base::Time value to a base::TimeTicks value. The conversion isn't
302 // exact, but by capturing Time::Now() as early as possible, the likelihood of a 335 // exact, but by capturing Time::Now() as early as possible, the likelihood of a
303 // clock change between it and process start is as low as possible. There is 336 // clock change between it and process start is as low as possible. There is
304 // also the time taken to synchronously resolve base::Time::Now() and 337 // also the time taken to synchronously resolve base::Time::Now() and
305 // base::TimeTicks::Now() at play, but in practice it is pretty much instant 338 // base::TimeTicks::Now() at play, but in practice it is pretty much instant
306 // compared to multi-seconds startup timings. 339 // compared to multi-seconds startup timings.
307 base::TimeTicks StartupTimeToTimeTicks(const base::Time& time) { 340 base::TimeTicks StartupTimeToTimeTicks(const base::Time& time) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 scoped_ptr<base::Environment> env(base::Environment::Create()); 411 scoped_ptr<base::Environment> env(base::Environment::Create());
379 std::string ticks_string; 412 std::string ticks_string;
380 int64 time_int = 0; 413 int64 time_int = 0;
381 if (env->GetVar(kChromeMainTicksEnvVar, &ticks_string) && 414 if (env->GetVar(kChromeMainTicksEnvVar, &ticks_string) &&
382 base::StringToInt64(ticks_string, &time_int)) { 415 base::StringToInt64(ticks_string, &time_int)) {
383 return base::TimeTicks::FromInternalValue(time_int); 416 return base::TimeTicks::FromInternalValue(time_int);
384 } 417 }
385 return base::TimeTicks(); 418 return base::TimeTicks();
386 } 419 }
387 420
421 // Logs the Startup.TimeSinceLastStartup histogram. Obtains the timestamp of the
422 // last startup from |pref_service| and overwrites it with the timestamp of the
423 // current startup. If the startup temperature has been set by
424 // RecordBrowserMainMessageLoopStart, the time since last startup is also logged
425 // to an histogram suffixed with the startup temperature.
426 void RecordTimeSinceLastStartup(PrefService* pref_service) {
427 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
428 DCHECK(pref_service);
429
430 // Get the timestamp of the current startup.
431 const base::Time process_start_time =
432 base::CurrentProcessInfo::CreationTime();
433
434 // Get the timestamp of the last startup from |pref_service|.
435 const int64_t last_startup_timestamp_internal =
436 pref_service->GetInt64(prefs::kLastStartupTimestamp);
437 if (last_startup_timestamp_internal != 0) {
438 // Log the Startup.TimeSinceLastStartup histogram.
439 const base::Time last_startup_timestamp =
440 base::Time::FromInternalValue(last_startup_timestamp_internal);
441 const base::TimeDelta time_since_last_startup =
442 process_start_time - last_startup_timestamp;
443 const int minutes_since_last_startup = time_since_last_startup.InMinutes();
444
445 // Ignore negative values, which can be caused by system clock changes.
446 if (minutes_since_last_startup >= 0) {
447 UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(
448 UMA_HISTOGRAM_TIME_IN_MINUTES_MONTH_RANGE,
449 "Startup.TimeSinceLastStartup", minutes_since_last_startup);
450 }
451 }
452
453 // Write the timestamp of the current startup in |pref_service|.
454 pref_service->SetInt64(prefs::kLastStartupTimestamp,
455 process_start_time.ToInternalValue());
456 #endif // defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
457 }
458
459 // Logs the Startup.SameVersionStartupCount histogram. Relies on |pref_service|
460 // to know information about the previous startups and store information for
461 // future ones. Returns the number of startups with the same version count that
462 // was logged.
463 int RecordSameVersionStartupCount(PrefService* pref_service) {
464 DCHECK(pref_service);
465
466 const std::string current_version = version_info::GetVersionNumber();
467
468 int startups_with_current_version = 0;
469 if (current_version == pref_service->GetString(prefs::kLastStartupVersion)) {
470 startups_with_current_version =
471 pref_service->GetInteger(prefs::kSameVersionStartupCount);
472 ++startups_with_current_version;
473 pref_service->SetInteger(prefs::kSameVersionStartupCount,
474 startups_with_current_version);
475 } else {
476 startups_with_current_version = 1;
477 pref_service->SetString(prefs::kLastStartupVersion, current_version);
478 pref_service->SetInteger(prefs::kSameVersionStartupCount, 1);
479 }
480
481 UMA_HISTOGRAM_COUNTS_100("Startup.SameVersionStartupCount",
482 startups_with_current_version);
483 return startups_with_current_version;
484 }
485
388 } // namespace 486 } // namespace
389 487
390 void RegisterPrefs(PrefRegistrySimple* registry) { 488 void RegisterPrefs(PrefRegistrySimple* registry) {
391 DCHECK(registry); 489 DCHECK(registry);
392 registry->RegisterInt64Pref(prefs::kLastStartupTimestamp, 0); 490 registry->RegisterInt64Pref(prefs::kLastStartupTimestamp, 0);
393 registry->RegisterStringPref(prefs::kLastStartupVersion, std::string()); 491 registry->RegisterStringPref(prefs::kLastStartupVersion, std::string());
394 registry->RegisterIntegerPref(prefs::kSameVersionStartupCount, 0); 492 registry->RegisterIntegerPref(prefs::kSameVersionStartupCount, 0);
395 } 493 }
396 494
397 bool WasNonBrowserUIDisplayed() { 495 bool WasNonBrowserUIDisplayed() {
(...skipping 23 matching lines...) Expand all
421 } 519 }
422 520
423 void RecordExeMainEntryPointTime(const base::Time& time) { 521 void RecordExeMainEntryPointTime(const base::Time& time) {
424 const std::string exe_load_ticks = 522 const std::string exe_load_ticks =
425 base::Int64ToString(StartupTimeToTimeTicks(time).ToInternalValue()); 523 base::Int64ToString(StartupTimeToTimeTicks(time).ToInternalValue());
426 scoped_ptr<base::Environment> env(base::Environment::Create()); 524 scoped_ptr<base::Environment> env(base::Environment::Create());
427 env->SetVar(kChromeMainTicksEnvVar, exe_load_ticks); 525 env->SetVar(kChromeMainTicksEnvVar, exe_load_ticks);
428 } 526 }
429 527
430 void RecordBrowserMainMessageLoopStart(const base::TimeTicks& ticks, 528 void RecordBrowserMainMessageLoopStart(const base::TimeTicks& ticks,
431 bool is_first_run) { 529 bool is_first_run,
432 RecordHardFaultHistogram(is_first_run); 530 PrefService* pref_service) {
531 int same_version_startup_count = 0;
532 if (pref_service)
533 same_version_startup_count = RecordSameVersionStartupCount(pref_service);
534 // Keep RecordHardFaultHistogram() first as much as possible as many other
535 // histograms depend on it setting |g_startup_temperature|.
536 RecordHardFaultHistogram(same_version_startup_count);
537 if (pref_service)
538 RecordTimeSinceLastStartup(pref_service);
433 RecordSystemUptimeHistogram(); 539 RecordSystemUptimeHistogram();
434 RecordMainEntryTimeHistogram(); 540 RecordMainEntryTimeHistogram();
435 541
436 const base::TimeTicks& process_creation_ticks = 542 const base::TimeTicks& process_creation_ticks =
437 g_process_creation_ticks.Get(); 543 g_process_creation_ticks.Get();
438 if (!is_first_run && !process_creation_ticks.is_null()) { 544 if (!is_first_run && !process_creation_ticks.is_null()) {
439 UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( 545 UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
440 UMA_HISTOGRAM_LONG_TIMES_100, "Startup.BrowserMessageLoopStartTime", 546 UMA_HISTOGRAM_LONG_TIMES_100, "Startup.BrowserMessageLoopStartTime",
441 process_creation_ticks, ticks); 547 process_creation_ticks, ticks);
442 } 548 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 587
482 // Process create to chrome.dll:main(). Reported as a histogram only as 588 // Process create to chrome.dll:main(). Reported as a histogram only as
483 // the other two events above are sufficient for tracing purposes. 589 // the other two events above are sufficient for tracing purposes.
484 UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE( 590 UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(
485 UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ProcessCreateToDllMain", 591 UMA_HISTOGRAM_LONG_TIMES, "Startup.LoadTime.ProcessCreateToDllMain",
486 g_main_entry_point_ticks.Get() - process_creation_ticks); 592 g_main_entry_point_ticks.Get() - process_creation_ticks);
487 } 593 }
488 } 594 }
489 } 595 }
490 596
491 void RecordTimeSinceLastStartup(PrefService* pref_service) {
492 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
493 DCHECK(pref_service);
494
495 // Get the timestamp of the current startup.
496 const base::Time process_start_time =
497 base::CurrentProcessInfo::CreationTime();
498
499 // Get the timestamp of the last startup from |pref_service|.
500 const int64_t last_startup_timestamp_internal =
501 pref_service->GetInt64(prefs::kLastStartupTimestamp);
502 if (last_startup_timestamp_internal != 0) {
503 // Log the Startup.TimeSinceLastStartup histogram.
504 const base::Time last_startup_timestamp =
505 base::Time::FromInternalValue(last_startup_timestamp_internal);
506 const base::TimeDelta time_since_last_startup =
507 process_start_time - last_startup_timestamp;
508 const int minutes_since_last_startup = time_since_last_startup.InMinutes();
509
510 // Ignore negative values, which can be caused by system clock changes.
511 if (minutes_since_last_startup >= 0) {
512 UMA_HISTOGRAM_WITH_STARTUP_TEMPERATURE(
513 UMA_HISTOGRAM_TIME_IN_MINUTES_MONTH_RANGE,
514 "Startup.TimeSinceLastStartup", minutes_since_last_startup);
515 }
516 }
517
518 // Write the timestamp of the current startup in |pref_service|.
519 pref_service->SetInt64(prefs::kLastStartupTimestamp,
520 process_start_time.ToInternalValue());
521 #endif // defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
522 }
523
524 void RecordStartupCount(PrefService* pref_service) {
525 DCHECK(pref_service);
526
527 const std::string current_version = version_info::GetVersionNumber();
528
529 int startups_with_current_version = 0;
530 if (current_version == pref_service->GetString(prefs::kLastStartupVersion)) {
531 startups_with_current_version =
532 pref_service->GetInteger(prefs::kSameVersionStartupCount);
533 ++startups_with_current_version;
534 pref_service->SetInteger(prefs::kSameVersionStartupCount,
535 startups_with_current_version);
536 } else {
537 startups_with_current_version = 1;
538 pref_service->SetString(prefs::kLastStartupVersion, current_version);
539 pref_service->SetInteger(prefs::kSameVersionStartupCount, 1);
540 }
541
542 UMA_HISTOGRAM_COUNTS_100("Startup.SameVersionStartupCount",
543 startups_with_current_version);
544 }
545
546 void RecordBrowserWindowDisplay(const base::TimeTicks& ticks) { 597 void RecordBrowserWindowDisplay(const base::TimeTicks& ticks) {
547 static bool is_first_call = true; 598 static bool is_first_call = true;
548 if (!is_first_call || ticks.is_null()) 599 if (!is_first_call || ticks.is_null())
549 return; 600 return;
550 is_first_call = false; 601 is_first_call = false;
551 if (WasNonBrowserUIDisplayed() || g_process_creation_ticks.Get().is_null()) 602 if (WasNonBrowserUIDisplayed() || g_process_creation_ticks.Get().is_null())
552 return; 603 return;
553 604
554 UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE( 605 UMA_HISTOGRAM_AND_TRACE_WITH_STARTUP_TEMPERATURE(
555 UMA_HISTOGRAM_LONG_TIMES, "Startup.BrowserWindowDisplay", 606 UMA_HISTOGRAM_LONG_TIMES, "Startup.BrowserWindowDisplay",
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
651 702
652 base::TimeTicks MainEntryPointTicks() { 703 base::TimeTicks MainEntryPointTicks() {
653 return g_main_entry_point_ticks.Get(); 704 return g_main_entry_point_ticks.Get();
654 } 705 }
655 706
656 StartupTemperature GetStartupTemperature() { 707 StartupTemperature GetStartupTemperature() {
657 return g_startup_temperature; 708 return g_startup_temperature;
658 } 709 }
659 710
660 } // namespace startup_metric_utils 711 } // namespace startup_metric_utils
OLDNEW
« no previous file with comments | « components/startup_metric_utils/browser/startup_metric_utils.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698