Bug 541185: Fall back on clock_getres() when resolution detection fails, and remove bogus upper-bound sanity check. r=roc
authorChris Jones <jones.chris.g@gmail.com>
Mon, 01 Mar 2010 15:44:05 -0600
changeset 38821 cdc530fc500eee1dcad367634e6634039f22524b
parent 38820 dbb530e1ac89abc923c8907e1ca16fc6b57e4e85
child 38822 b7b5c61b1af8c2d2beea507ebc943b59c70e13d3
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs541185
milestone1.9.3a3pre
Bug 541185: Fall back on clock_getres() when resolution detection fails, and remove bogus upper-bound sanity check. r=roc
xpcom/ds/TimeStamp_posix.cpp
xpcom/tests/TestTimeStamp.cpp
--- a/xpcom/ds/TimeStamp_posix.cpp
+++ b/xpcom/ds/TimeStamp_posix.cpp
@@ -53,41 +53,45 @@
 static PRUint64 sResolution;
 static PRUint64 sResolutionSigDigs;
 
 static const PRUint16 kNsPerUs   =       1000;
 static const PRUint64 kNsPerMs   =    1000000;
 static const PRUint64 kNsPerSec  = 1000000000; 
 static const double kNsPerSecd   = 1000000000.0;
 
+static PRUint64
+TimespecToNs(const struct timespec& ts)
+{
+  PRUint64 baseNs = PRUint64(ts.tv_sec) * kNsPerSec;
+  return baseNs + PRUint64(ts.tv_nsec);
+}
 
 static PRUint64
 ClockTimeNs()
 {
   struct timespec ts;
   // this can't fail: we know &ts is valid, and TimeStamp::Init()
   // checks that CLOCK_MONOTONIC is supported (and aborts if not)
   clock_gettime(CLOCK_MONOTONIC, &ts);
 
   // tv_sec is defined to be relative to an arbitrary point in time,
   // but it would be madness for that point in time to be earlier than
   // the Epoch.  So we can safely assume that even if time_t is 32
   // bits, tv_sec won't overflow while the browser is open.  Revisit
   // this argument if we're still building with 32-bit time_t around
   // the year 2037.
-  PRUint64 baseNs = PRUint64(ts.tv_sec) * kNsPerSec;
-
-  return baseNs + PRUint64(ts.tv_nsec);
+  return TimespecToNs(ts);
 }
 
 static PRUint64
 ClockResolutionNs()
 {
-  // NB: why not use clock_getres()?  Two reasons: (i) it might lie,
-  // and (ii) it might return an "ideal" resolution that while
+  // NB: why not rely on clock_getres()?  Two reasons: (i) it might
+  // lie, and (ii) it might return an "ideal" resolution that while
   // theoretically true, could never be measured in practice.  Since
   // clock_gettime() likely involves a system call on your platform,
   // the "actual" timing resolution shouldn't be lower than syscall
   // overhead.
 
   PRUint64 start = ClockTimeNs();
   PRUint64 end = ClockTimeNs();
   PRUint64 minres = (end - start);
@@ -100,21 +104,29 @@ ClockResolutionNs()
     end = ClockTimeNs();
 
     PRUint64 candidate = (start - end);
     if (candidate < minres)
       minres = candidate;
   }
 
   if (0 == minres) {
-    NS_WARNING("the clock resolution is *not* 1ns, something's wrong");
-    minres = 1;                 // to avoid /0
+    // measurable resolution is either incredibly low, ~1ns, or very
+    // high.  fall back on clock_getres()
+    struct timespec ts;
+    clock_getres(CLOCK_MONOTONIC, &ts);
+
+    minres = TimespecToNs(ts);
   }
-  if (minres / kNsPerMs)
-    NS_WARNING("the clock resolution is *not* >=1ms, something's wrong");
+
+  if (0 == minres) {
+    // clock_getres probably failed.  fall back on NSPR's resolution
+    // assumption
+    minres = 1 * kNsPerMs;
+  }
 
   return minres;
 }
 
 
 namespace mozilla {
 
 double
--- a/xpcom/tests/TestTimeStamp.cpp
+++ b/xpcom/tests/TestTimeStamp.cpp
@@ -116,12 +116,13 @@ int main(int argc, char** argv)
     Assert(td.ToSeconds() < 20.0, "TimeStamp difference upper bound");
     td = ts - ts2;
     Assert(td.ToSeconds() < -1.0, "TimeStamp negative difference lower bound");
     Assert(td.ToSeconds() > -20.0, "TimeStamp negative difference upper bound");
 
     double resolution = TimeDuration::Resolution().ToSecondsSigDigits();
     printf(" (platform timer resolution is ~%g s)\n", resolution);
     Assert(0.000000001 < resolution, "Time resolution is sane");
-    Assert(resolution <= 0.001, "Time resolution as good as NSPR's worst");
+    // Don't upper-bound sanity check ... although NSPR reports 1ms
+    // resolution, it might be lying, so we shouldn't compare with it
 
     return gFailCount > 0;
 }