Bug 1542833 - Collect cold startup scalar r=chutten,florian
authorDoug Thayer <dothayer@mozilla.com>
Mon, 29 Apr 2019 17:15:23 +0000
changeset 471779 cb964035e6395a6da86e54c3e34cc5a5c589b574
parent 471778 f348b1ddb6c6aff4b1cb72dd519768c213de8b9a
child 471780 c58def4246acd844cda042938d426a35320eafba
push id35934
push usershindli@mozilla.com
push dateMon, 29 Apr 2019 21:53:38 +0000
treeherdermozilla-central@f6766ba4ac77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerschutten, florian
bugs1542833
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1542833 - Collect cold startup scalar r=chutten,florian Differential Revision: https://phabricator.services.mozilla.com/D27953
browser/components/BrowserGlue.jsm
toolkit/components/startup/nsAppStartup.cpp
toolkit/components/startup/public/nsIAppStartup.idl
toolkit/components/telemetry/Scalars.yaml
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -1249,16 +1249,34 @@ BrowserGlue.prototype = {
 
   _firstWindowTelemetry(aWindow) {
     let scaling = aWindow.devicePixelRatio * 100;
     try {
       Services.telemetry.getHistogramById("DISPLAY_SCALING").add(scaling);
     } catch (ex) {}
   },
 
+  _collectStartupConditionsTelemetry() {
+    let nowSeconds = Math.round(Date.now() / 1000);
+    // Don't include cases where we don't have the pref. This rules out the first install
+    // as well as the first run of a build since this was introduced. These could by some
+    // definitions be referred to as "cold" startups, but probably not since we likely
+    // just wrote many of the files we use to disk. This way we should approximate a lower
+    // bound to the number of cold startups rather than an upper bound.
+    let lastCheckSeconds = Services.prefs.getIntPref("browser.startup.lastColdStartupCheck", nowSeconds);
+    Services.prefs.setIntPref("browser.startup.lastColdStartupCheck", nowSeconds);
+    try {
+      let secondsSinceLastOSRestart = Services.startup.secondsSinceLastOSRestart;
+      let isColdStartup = nowSeconds - secondsSinceLastOSRestart > lastCheckSeconds;
+      Services.telemetry.scalarSet("startup.is_cold", isColdStartup);
+    } catch (ex) {
+      Cu.reportError(ex);
+    }
+  },
+
   // the first browser window has finished initializing
   _onFirstWindowLoaded: function BG__onFirstWindowLoaded(aWindow) {
     TabCrashHandler.init();
     if (AppConstants.MOZ_CRASHREPORTER) {
       PluginCrashReporter.init();
     }
 
     ProcessHangMonitor.init();
@@ -1324,16 +1342,18 @@ BrowserGlue.prototype = {
 
     AboutPrivateBrowsingHandler.init();
 
     PageActions.init();
 
     this._firstWindowTelemetry(aWindow);
     this._firstWindowLoaded();
 
+    this._collectStartupConditionsTelemetry();
+
     // Set the default favicon size for UI views that use the page-icon protocol.
     PlacesUtils.favicons.setDefaultIconURIPreferredSize(16 * aWindow.devicePixelRatio);
     this._setPrefExpectations();
     this._matchCBCategory();
 
     // This observes the entire privacy.trackingprotection.* pref tree.
     Services.prefs.addObserver("privacy.trackingprotection", this._matchCBCategory);
     Services.prefs.addObserver("network.cookie.cookieBehavior", this._matchCBCategory);
--- a/toolkit/components/startup/nsAppStartup.cpp
+++ b/toolkit/components/startup/nsAppStartup.cpp
@@ -42,29 +42,35 @@
 #include "jsapi.h"
 #include "js/Date.h"
 #include "prenv.h"
 #include "nsAppDirectoryServiceDefs.h"
 
 #if defined(XP_WIN)
 // Prevent collisions with nsAppStartup::GetStartupInfo()
 #  undef GetStartupInfo
+
+#  include <windows.h>
+#elif defined(XP_DARWIN)
+#  include <mach/mach_time.h>
 #endif
 
 #include "mozilla/IOInterposer.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/StartupTimeline.h"
 
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 #define kPrefLastSuccess "toolkit.startup.last_success"
 #define kPrefMaxResumedCrashes "toolkit.startup.max_resumed_crashes"
 #define kPrefRecentCrashes "toolkit.startup.recent_crashes"
 #define kPrefAlwaysUseSafeMode "toolkit.startup.always_use_safe_mode"
 
+#define kNanosecondsPerSecond 1000000000.0
+
 #if defined(XP_WIN)
 #  include "mozilla/perfprobe.h"
 /**
  * Events sent to the system for profiling purposes
  */
 // Keep them syncronized with the .mof file
 
 // Process-wide GUID, used by the OS to differentiate sources
@@ -537,16 +543,35 @@ nsAppStartup::GetWasRestarted(bool *aRes
    * be unset or set to the empty string depending on the underlying platform
    * thus we have to check if the variable is present and not empty. */
   *aResult = mozAppRestart && (strcmp(mozAppRestart, "") != 0);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsAppStartup::GetSecondsSinceLastOSRestart(int64_t *aResult) {
+#if defined(XP_WIN)
+  *aResult = int64_t(GetTickCount64() / 1000ull);
+  return NS_OK;
+#elif defined(XP_DARWIN)
+  uint64_t absTime = mach_absolute_time();
+  mach_timebase_info_data_t timebaseInfo;
+  mach_timebase_info(&timebaseInfo);
+  double toNanoseconds =
+      double(timebaseInfo.numer) / double(timebaseInfo.denom);
+  *aResult =
+      std::llround(double(absTime) * toNanoseconds / kNanosecondsPerSecond);
+  return NS_OK;
+#else
+  return NS_ERROR_NOT_IMPLEMENTED;
+#endif
+}
+
+NS_IMETHODIMP
 nsAppStartup::SetInterrupted(bool aInterrupted) {
   mInterrupted = aInterrupted;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAppStartup::GetInterrupted(bool *aInterrupted) {
   *aInterrupted = mInterrupted;
--- a/toolkit/components/startup/public/nsIAppStartup.idl
+++ b/toolkit/components/startup/public/nsIAppStartup.idl
@@ -151,16 +151,21 @@ interface nsIAppStartup : nsISupports
     readonly attribute boolean restarting;
 
     /**
      * True if this is the startup following restart, i.e. if the application
      * was restarted using quit(eRestart*).
      */
     readonly attribute boolean wasRestarted;
 
+    /**
+     * The number of seconds since the OS was last rebooted
+     */
+    readonly attribute int64_t secondsSinceLastOSRestart;
+
     /** 
      * Returns an object with main, process, firstPaint, sessionRestored properties.
      * Properties may not be available depending on platform or application
      */
     [implicit_jscontext] jsval getStartupInfo();
 
     /**
      * True if startup was interrupted by an interactive prompt.
--- a/toolkit/components/telemetry/Scalars.yaml
+++ b/toolkit/components/telemetry/Scalars.yaml
@@ -3584,16 +3584,30 @@ startup:
     kind: string
     notification_emails:
       - dtownsend@mozilla.com
       - rtestard@mozilla.com
     release_channel_collection: opt-out
     record_in_processes:
       - main
 
+  is_cold:
+    bug_numbers:
+      - 1542833
+    description: >
+      Whether or not this startup is the first startup since OS reboot (according to our
+      best guess.)
+    expires: never
+    kind: boolean
+    notification_emails:
+      - dothayer@mozilla.com
+    release_channel_collection: opt-out
+    record_in_processes:
+      - 'main'
+
 script.preloader:
   mainthread_recompile:
     bug_numbers:
       - 1364235
     description:
       How many times we ended up recompiling a script from the script preloader
       on the main thread.
     expires: "73"