Bug 852250 - When restarting recompute the process startup timestamp instead of using the timestamp stored it in MOZ_APP_RESTART during the shutdown procedure. r=nfroyd
authorGabriele Svelto <gsvelto@mozilla.com>
Wed, 31 Jul 2013 12:51:58 +0200
changeset 153090 612a421df3aee4a8a6e3f29306443b735c98aa81
parent 153089 33600eab273edec69da64c8fa97fb012279c5f78
child 153091 408a7705c7a509e6047741f24240a6b1b31c4c8b
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnfroyd
bugs852250
milestone25.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 852250 - When restarting recompute the process startup timestamp instead of using the timestamp stored it in MOZ_APP_RESTART during the shutdown procedure. r=nfroyd
xpcom/ds/TimeStamp.cpp
xpcom/ds/TimeStamp.h
xpcom/ds/TimeStamp_darwin.cpp
xpcom/ds/TimeStamp_posix.cpp
xpcom/ds/TimeStamp_windows.cpp
xpcom/ds/moz.build
new file mode 100644
--- /dev/null
+++ b/xpcom/ds/TimeStamp.cpp
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Implementation of the OS-independent methods of the TimeStamp class
+ */
+
+#include "mozilla/TimeStamp.h"
+#include "prenv.h"
+
+namespace mozilla {
+
+TimeStamp TimeStamp::sFirstTimeStamp;
+TimeStamp TimeStamp::sProcessCreation;
+
+TimeStamp
+TimeStamp::ProcessCreation(bool& aIsInconsistent)
+{
+  aIsInconsistent = false;
+
+  if (sProcessCreation.IsNull()) {
+    char *mozAppRestart = PR_GetEnv("MOZ_APP_RESTART");
+    TimeStamp ts;
+
+    /* When calling PR_SetEnv() with an empty value the existing variable may
+     * 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. */
+    if (mozAppRestart && (strcmp(mozAppRestart, "") != 0)) {
+      /* Firefox was restarted, use the first time-stamp we've taken as the new
+       * process startup time and unset MOZ_APP_RESTART. */
+      ts = sFirstTimeStamp;
+      PR_SetEnv("MOZ_APP_RESTART=");
+    } else {
+      TimeStamp now = Now();
+      uint64_t uptime = ComputeProcessUptime();
+
+      ts = now - TimeDuration::FromMicroseconds(uptime);
+
+      if ((ts > sFirstTimeStamp) || (uptime == 0)) {
+        /* If the process creation timestamp was inconsistent replace it with
+         * the first one instead and notify that a telemetry error was
+         * detected. */
+        aIsInconsistent = true;
+        ts = sFirstTimeStamp;
+      }
+    }
+
+    sProcessCreation = ts;
+  }
+
+  return sProcessCreation;
+}
+
+void
+TimeStamp::RecordProcessRestart()
+{
+  PR_SetEnv("MOZ_APP_RESTART=1");
+  sProcessCreation = TimeStamp();
+}
+
+} // namespace mozilla
--- a/xpcom/ds/TimeStamp.h
+++ b/xpcom/ds/TimeStamp.h
@@ -338,16 +338,26 @@ private:
   friend struct IPC::ParamTraits<mozilla::TimeStamp>;
   friend void StartupTimelineRecordExternal(int, uint64_t);
 
   TimeStamp(TimeStampValue aValue) : mValue(aValue) {}
 
   static TimeStamp Now(bool aHighResolution);
 
   /**
+   * Computes the uptime of the current process in microseconds. The result
+   * is platform-dependent and needs to be checked against existing timestamps
+   * for consistency.
+   *
+   * @returns The number of microseconds since the calling process was started
+   *          or 0 if an error was encountered while computing the uptime
+   */
+  static uint64_t ComputeProcessUptime();
+
+  /**
    * When built with PRIntervalTime, a value of 0 means this instance
    * is "null". Otherwise, the low 32 bits represent a PRIntervalTime,
    * and the high 32 bits represent a counter of the number of
    * rollovers of PRIntervalTime that we've seen. This counter starts
    * at 1 to avoid a real time colliding with the "null" value.
    * 
    * PR_INTERVAL_MAX is set at 100,000 ticks per second. So the minimum
    * time to wrap around is about 2^64/100000 seconds, i.e. about
--- a/xpcom/ds/TimeStamp_darwin.cpp
+++ b/xpcom/ds/TimeStamp_darwin.cpp
@@ -19,17 +19,16 @@
 #include <mach/mach_time.h>
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/sysctl.h>
 #include <time.h>
 
 #include "mozilla/TimeStamp.h"
 #include "nsCRT.h"
-#include "prenv.h"
 #include "prprf.h"
 
 // Estimate of the smallest duration of time we can measure.
 static uint64_t sResolution;
 static uint64_t sResolutionSigDigs;
 
 static const uint64_t kNsPerMs   =    1000000;
 static const uint64_t kUsPerSec  =    1000000;
@@ -78,19 +77,16 @@ ClockResolutionNs()
     minres = 1 * kNsPerMs;
   }
 
   return minres;
 }
 
 namespace mozilla {
 
-TimeStamp TimeStamp::sFirstTimeStamp;
-TimeStamp TimeStamp::sProcessCreation;
-
 double
 TimeDuration::ToSeconds() const
 {
   NS_ABORT_IF_FALSE(gInitialized, "calling TimeDuration too early");
   return (mValue * sNsPerTick) / kNsPerSecd;
 }
 
 double
@@ -171,18 +167,18 @@ TimeStamp
 TimeStamp::Now(bool aHighResolution)
 {
   return TimeStamp(ClockTime());
 }
 
 // Computes and returns the process uptime in microseconds.
 // Returns 0 if an error was encountered.
 
-static uint64_t
-ComputeProcessUptime()
+uint64_t
+TimeStamp::ComputeProcessUptime()
 {
   struct timeval tv;
   int rv = gettimeofday(&tv, NULL);
 
   if (rv == -1) {
     return 0;
   }
 
@@ -207,47 +203,9 @@ ComputeProcessUptime()
   uint64_t now = (tv.tv_sec * kUsPerSec) + tv.tv_usec;
 
   if (startTime > now)
     return 0;
 
   return now - startTime;
 }
 
-TimeStamp
-TimeStamp::ProcessCreation(bool& aIsInconsistent)
-{
-  aIsInconsistent = false;
-
-  if (sProcessCreation.IsNull()) {
-    char *mozAppRestart = PR_GetEnv("MOZ_APP_RESTART");
-    TimeStamp ts;
-
-    if (mozAppRestart) {
-      ts = TimeStamp(nsCRT::atoll(mozAppRestart));
-    } else {
-      TimeStamp now = TimeStamp::Now();
-      uint64_t uptime = ComputeProcessUptime();
-
-      ts = now - TimeDuration::FromMicroseconds(uptime);
-
-      if ((ts > sFirstTimeStamp) || (uptime == 0)) {
-        // If the process creation timestamp was inconsistent replace it with the
-        // first one instead and notify that a telemetry error was detected.
-        aIsInconsistent = true;
-        ts = sFirstTimeStamp;
-      }
-    }
-
-    sProcessCreation = ts;
-  }
-
-  return sProcessCreation;
-}
-
-void
-TimeStamp::RecordProcessRestart()
-{
-  PR_SetEnv(PR_smprintf("MOZ_APP_RESTART=%lld", ClockTime()));
-  sProcessCreation = TimeStamp();
-}
-
-}
+} // namespace mozilla
--- a/xpcom/ds/TimeStamp_posix.cpp
+++ b/xpcom/ds/TimeStamp_posix.cpp
@@ -43,17 +43,16 @@
 #define KP_START_USEC ki_start.tv_usec
 #else
 #define KP_START_SEC p_ustart_sec
 #define KP_START_USEC p_ustart_usec
 #endif
 
 #include "mozilla/TimeStamp.h"
 #include "nsCRT.h"
-#include "prenv.h"
 #include "prprf.h"
 #include "prthread.h"
 
 // Estimate of the smallest duration of time we can measure.
 static uint64_t sResolution;
 static uint64_t sResolutionSigDigs;
 
 static const uint16_t kNsPerUs   =       1000;
@@ -127,19 +126,16 @@ ClockResolutionNs()
     minres = 1 * kNsPerMs;
   }
 
   return minres;
 }
 
 namespace mozilla {
 
-TimeStamp TimeStamp::sFirstTimeStamp;
-TimeStamp TimeStamp::sProcessCreation;
-
 double
 TimeDuration::ToSeconds() const
 {
   return double(mValue) / kNsPerSecd;
 }
 
 double
 TimeDuration::ToSecondsSigDigits() const
@@ -278,44 +274,44 @@ ComputeProcessUptimeThread(void *aTime)
   uint64_t selfJiffies = JiffiesSinceBoot("/proc/self/stat");
 
   if (!threadJiffies || !selfJiffies)
     return;
 
   *uptime = ((threadJiffies - selfJiffies) * kNsPerSec) / hz;
 }
 
-// Computes and returns the process uptime in ns on Linux & its derivatives.
+// Computes and returns the process uptime in us on Linux & its derivatives.
 // Returns 0 if an error was encountered.
 
-static uint64_t
-ComputeProcessUptime()
+uint64_t
+TimeStamp::ComputeProcessUptime()
 {
   uint64_t uptime = 0;
   PRThread *thread = PR_CreateThread(PR_USER_THREAD,
                                      ComputeProcessUptimeThread,
                                      &uptime,
                                      PR_PRIORITY_NORMAL,
                                      PR_LOCAL_THREAD,
                                      PR_JOINABLE_THREAD,
                                      0);
 
   PR_JoinThread(thread);
 
-  return uptime;
+  return uptime / kNsPerUs;
 }
 
 #elif defined(__DragonFly__) || defined(__FreeBSD__) \
       || defined(__NetBSD__) || defined(__OpenBSD__)
 
-// Computes and returns the process uptime in ns on various BSD flavors.
+// Computes and returns the process uptime in us on various BSD flavors.
 // Returns 0 if an error was encountered.
 
-static uint64_t
-ComputeProcessUptime()
+uint64_t
+TimeStamp::ComputeProcessUptime()
 {
   struct timespec ts;
   int rv = clock_gettime(CLOCK_REALTIME, &ts);
 
   if (rv == -1) {
     return 0;
   }
 
@@ -340,60 +336,22 @@ ComputeProcessUptime()
 
   uint64_t startTime = ((uint64_t)proc.KP_START_SEC * kNsPerSec)
     + (proc.KP_START_USEC * kNsPerUs);
   uint64_t now = ((uint64_t)ts.tv_sec * kNsPerSec) + ts.tv_nsec;
 
   if (startTime > now)
     return 0;
 
-  return (now - startTime);
+  return (now - startTime) / kNsPerUs;
 }
 
 #else
 
-static uint64_t
-ComputeProcessUptime()
+uint64_t
+TimeStamp::ComputeProcessUptime()
 {
   return 0;
 }
 
 #endif
 
-TimeStamp
-TimeStamp::ProcessCreation(bool& aIsInconsistent)
-{
-  aIsInconsistent = false;
-
-  if (sProcessCreation.IsNull()) {
-    char *mozAppRestart = PR_GetEnv("MOZ_APP_RESTART");
-    TimeStamp ts;
-
-    if (mozAppRestart) {
-      ts = TimeStamp(nsCRT::atoll(mozAppRestart));
-    } else {
-      TimeStamp now = TimeStamp::Now();
-      uint64_t uptime = ComputeProcessUptime();
-
-      ts = now - TimeDuration::FromMicroseconds(uptime / 1000);
-
-      if ((ts > sFirstTimeStamp) || (uptime == 0)) {
-        // If the process creation timestamp was inconsistent replace it with the
-        // first one instead and notify that a telemetry error was detected.
-        aIsInconsistent = true;
-        ts = sFirstTimeStamp;
-      }
-    }
-
-    sProcessCreation = ts;
-  }
-
-  return sProcessCreation;
-}
-
-void
-TimeStamp::RecordProcessRestart()
-{
-  PR_SetEnv(PR_smprintf("MOZ_APP_RESTART=%lld", ClockTimeNs()));
-  sProcessCreation = TimeStamp();
-}
-
-}
+} // namespace mozilla
--- a/xpcom/ds/TimeStamp_windows.cpp
+++ b/xpcom/ds/TimeStamp_windows.cpp
@@ -13,17 +13,16 @@
 
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/TimeStamp.h"
 #include <windows.h>
 
 #include "nsCRT.h"
 #include "prlog.h"
-#include "prenv.h"
 #include "prprf.h"
 #include <stdio.h>
 
 #include <intrin.h>
 
 #if defined(PR_LOGGING)
 // Log module for mozilla::TimeStamp for Windows logging...
 //
@@ -178,19 +177,16 @@ static ULONGLONG sFaultIntoleranceCheckp
 static DWORD sLastGTCResult = 0;
 
 // Higher part of the 64-bit value of MozGetTickCount64,
 // incremented atomically.
 static DWORD sLastGTCRollover = 0;
 
 namespace mozilla {
 
-TimeStamp TimeStamp::sFirstTimeStamp;
-TimeStamp TimeStamp::sProcessCreation;
-
 typedef ULONGLONG (WINAPI* GetTickCount64_t)();
 static GetTickCount64_t sGetTickCount64 = nullptr;
 
 // ----------------------------------------------------------------------------
 // Critical Section helper class
 // ----------------------------------------------------------------------------
 
 class AutoCriticalSection
@@ -557,21 +553,21 @@ TimeStamp::Now(bool aHighResolution)
   bool useQPC = (aHighResolution && sUseQPC);
 
   // Both values are in [mt] units.
   ULONGLONG QPC = useQPC ? PerformanceCounter() : uint64_t(0);
   ULONGLONG GTC = ms2mt(sGetTickCount64());
   return TimeStamp(TimeStampValue(GTC, QPC, useQPC));
 }
 
-// Computes and returns the current process uptime in microseconds.
-// Returns 0 if an error was encountered while computing the uptime.
+// Computes and returns the process uptime in microseconds.
+// Returns 0 if an error was encountered.
 
-static uint64_t
-ComputeProcessUptime()
+uint64_t
+TimeStamp::ComputeProcessUptime()
 {
   SYSTEMTIME nowSys;
   GetSystemTime(&nowSys);
 
   FILETIME now;
   bool success = SystemTimeToFileTime(&nowSys, &now);
 
   if (!success)
@@ -590,46 +586,9 @@ ComputeProcessUptime()
   ULARGE_INTEGER nowUsec = {
     now.dwLowDateTime,
     now.dwHighDateTime
   };
 
   return (nowUsec.QuadPart - startUsec.QuadPart) / 10ULL;
 }
 
-TimeStamp
-TimeStamp::ProcessCreation(bool& aIsInconsistent)
-{
-  aIsInconsistent = false;
-
-  if (sProcessCreation.IsNull()) {
-    char *mozAppRestart = PR_GetEnv("MOZ_APP_RESTART");
-    TimeStamp ts;
-
-    if (mozAppRestart) {
-      ts = TimeStamp(TimeStampValue(nsCRT::atoll(mozAppRestart), 0, false));
-    } else {
-      TimeStamp now = TimeStamp::Now();
-      uint64_t uptime = ComputeProcessUptime();
-      ts = now - TimeDuration::FromMicroseconds(static_cast<double>(uptime));
-
-      if ((ts > sFirstTimeStamp) || (uptime == 0)) {
-        // If the process creation timestamp was inconsistent replace it with the
-        // first one instead and notify that a telemetry error was detected.
-        aIsInconsistent = true;
-        ts = sFirstTimeStamp;
-      }
-    }
-
-    sProcessCreation = ts;
-  }
-
-  return sProcessCreation;
-}
-
-void
-TimeStamp::RecordProcessRestart()
-{
-  PR_SetEnv(PR_smprintf("MOZ_APP_RESTART=%lld", ms2mt(sGetTickCount64())));
-  sProcessCreation = TimeStamp();
-}
-
 } // namespace mozilla
--- a/xpcom/ds/moz.build
+++ b/xpcom/ds/moz.build
@@ -90,16 +90,17 @@ CPP_SOURCES += [
     'nsProperties.cpp',
     'nsStaticNameTable.cpp',
     'nsStringEnumerator.cpp',
     'nsSupportsArray.cpp',
     'nsSupportsArrayEnumerator.cpp',
     'nsSupportsPrimitives.cpp',
     'nsUnicharBuffer.cpp',
     'nsVariant.cpp',
+    'TimeStamp.cpp',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     CPP_SOURCES += [
         'TimeStamp_windows.cpp',
     ]
 elif CONFIG['HAVE_CLOCK_MONOTONIC']:
     CPP_SOURCES += [