Use clock_gettime(CLOCK_REALTIME) in DateTime.UtcNow (dotnet/coreclr#9772)
authorStephen Toub <stoub@microsoft.com>
Sat, 25 Feb 2017 01:39:44 +0000 (20:39 -0500)
committerJan Vorlicek <janvorli@microsoft.com>
Sat, 25 Feb 2017 01:39:44 +0000 (02:39 +0100)
gettimeofday() is currently used in DateTime.UtcNow.  Depending on the system, it may have accuracy and precision in line with either clock_gettime(CLOCK_REALTIME) or clock_gettime(CLOCK_REALTIME_COARSE), but in returning its data it's necessarily limited by struct timeval's tv_usec field (microseconds), whereas clock_gettime uses struct timespec which has tv_nsec (nanoseconds).  This commit switches to use clock_gettime(CLOCK_REALTIME) to gain the additional precision (though the FILETIME through which the data is returned only supports 100-nsec precision).  On my machine, there was no measurable impact to throughput.

Commit migrated from https://github.com/dotnet/coreclr/commit/3fe022eb723479d0b7acf17856e76a1973668ca6

src/coreclr/src/pal/src/file/filetime.cpp

index a8666b0..4e55e18 100644 (file)
@@ -504,23 +504,29 @@ PALAPI
 GetSystemTimeAsFileTime(
             OUT LPFILETIME lpSystemTimeAsFileTime)
 {
-    struct timeval Time;
-
     PERF_ENTRY(GetSystemTimeAsFileTime);
     ENTRY("GetSystemTimeAsFileTime(lpSystemTimeAsFileTime=%p)\n", 
           lpSystemTimeAsFileTime);
 
-    if ( gettimeofday( &Time, NULL ) != 0 )
+#if HAVE_WORKING_CLOCK_GETTIME
+    struct timespec Time;
+    if (clock_gettime(CLOCK_REALTIME, &Time) == 0)
     {
-        ASSERT("gettimeofday() failed");
-        /* no way to indicate failure, so set time to zero */
-        *lpSystemTimeAsFileTime = FILEUnixTimeToFileTime( 0, 0 );
+        *lpSystemTimeAsFileTime = FILEUnixTimeToFileTime( Time.tv_sec, Time.tv_nsec );
     }
-    else
+#else
+    struct timeval Time;
+    if (gettimeofday(&Time, NULL) == 0)
     {
         /* use (tv_usec * 1000) because 2nd arg is in nanoseconds */
-        *lpSystemTimeAsFileTime = FILEUnixTimeToFileTime( Time.tv_sec,
-                                                          Time.tv_usec * 1000 );
+        *lpSystemTimeAsFileTime = FILEUnixTimeToFileTime( Time.tv_sec, Time.tv_usec * 1000);
+    }
+#endif
+    else
+    {
+        /* no way to indicate failure, so set time to zero */
+        ASSERT("clock_gettime or gettimeofday failed");
+        *lpSystemTimeAsFileTime = FILEUnixTimeToFileTime( 0, 0 );
     }
 
     LOGEXIT("GetSystemTimeAsFileTime returns.\n");