Kaynağa Gözat

xplat: back short interval GetSystemTime calls via cpu-ticks

Oguz Bastemur 9 yıl önce
ebeveyn
işleme
f397b28036

+ 1 - 1
lib/Backend/InliningDecider.cpp

@@ -138,7 +138,7 @@ uint InliningDecider::InlinePolymorphicCallSite(Js::FunctionBody *const inliner,
     bool isConstructorCall;
     if (!profileData->GetPolymorphicCallSiteInfo(inliner, profiledCallSiteId, &isConstructorCall, functionBodyArray, functionBodyArrayLength))
     {
-        return false;
+        return 0;
     }
 
     uint inlineeCount = 0;

+ 1 - 1
lib/Common/PlatformAgnostic/DateTime.h

@@ -20,7 +20,7 @@ namespace DateTime
 
     public:
         double Now();
-        static double GetSystemTime();
+        double GetSystemTime();
 
         void Reset() { data.Reset(); }
     };

+ 4 - 0
lib/Common/PlatformAgnostic/DateTimeInternal.h

@@ -95,6 +95,10 @@ namespace DateTime
     class HiresTimerPlatformData
     {
     public:
+        double    cacheSysTime;
+        ULONGLONG cacheTick;
+
+        HiresTimerPlatformData():cacheSysTime(0), cacheTick(-1) { }
         void Reset() { /* dummy method for interface compatiblity */ }
     };
 

+ 1 - 1
lib/Runtime/PlatformAgnostic/Platform/CMakeLists.txt

@@ -2,8 +2,8 @@ project(CHAKRA_PLATFORM_AGNOSTIC)
 
 set(PL_SOURCE_FILES
   Common/UnicodeText.Common.cpp
+  Common/HiResTimer.cpp
   Linux/UnicodeText.ICU.cpp
-  Linux/HiResTimer.cpp
   Linux/NumbersUtility.cpp
   Linux/Thread.cpp
   Common/Trace.cpp

+ 31 - 9
lib/Runtime/PlatformAgnostic/Platform/Linux/HiResTimer.cpp → lib/Runtime/PlatformAgnostic/Platform/Common/HiResTimer.cpp

@@ -12,12 +12,9 @@ namespace PlatformAgnostic
 {
 namespace DateTime
 {
-
     // This method is expected to return UTC time (See MSDN GetSystemTime)
-    double HiResTimer::GetSystemTime()
+    inline static double GetSystemTimeREAL()
     {
-// todo: remove/move this when we have BSD/UNIX folder
-// todo-osx: mach_absolute_time
 #ifndef __APPLE__
         struct timespec fast_time;
         // method below returns UTC time. So, nothing else is needed
@@ -25,10 +22,9 @@ namespace DateTime
         if (clock_gettime(CLOCK_REALTIME, &fast_time) == 0)
         {
             return (fast_time.tv_sec * DateTimeTicks_PerSecond)
-                   + (int32_t) (fast_time.tv_nsec / 1e6);
+            + (int32_t) (fast_time.tv_nsec / 1e6);
         }
 #endif
-
         // in case of clock_gettime fails we use the implementation below
         struct tm utc_tm;
         struct timeval timeval;
@@ -56,18 +52,44 @@ namespace DateTime
             if(old_sec != new_sec)
             {
                 milliseconds = 999;
-            }  
-        }                      
+            }
+        }
 
         milliseconds = (utc_tm.tm_hour * DateTimeTicks_PerHour)
                         + (utc_tm.tm_min * DateTimeTicks_PerMinute)
                         + (utc_tm.tm_sec * DateTimeTicks_PerSecond)
                         + milliseconds;
 
-        return Js::DateUtilities::TvFromDate(1900 + utc_tm.tm_year, utc_tm.tm_mon, 
+        return Js::DateUtilities::TvFromDate(1900 + utc_tm.tm_year, utc_tm.tm_mon,
                                             utc_tm.tm_mday - 1, milliseconds);
     }
 
+#define INTERVAL_FOR_TICK_BACKUP 5
+    double HiResTimer::GetSystemTime()
+    {
+        ULONGLONG current = GetTickCount64();
+        ULONGLONG diff = current - data.cacheTick;
+
+        if (diff >= INTERVAL_FOR_TICK_BACKUP) // max *ms to respond system time changes
+        {
+            double currentTime = GetSystemTimeREAL();
+
+            // in case the system time wasn't updated backwards, and cache is still beyond...
+            if (currentTime > data.cacheSysTime && currentTime < data.cacheSysTime + INTERVAL_FOR_TICK_BACKUP)
+            {
+                return data.cacheSysTime + INTERVAL_FOR_TICK_BACKUP; // wait for real time
+            }
+
+            data.cacheSysTime = currentTime;
+            data.cacheTick = current;
+
+            return data.cacheSysTime;
+        }
+
+        return data.cacheSysTime + (double)diff;
+    }
+#undef INTERVAL_FOR_TICK_BACKUP
+
     double HiResTimer::Now()
     {
         return GetSystemTime();

+ 0 - 6
pal/inc/pal.h

@@ -1075,12 +1075,6 @@ typedef struct _SYSTEMTIME {
     WORD wMilliseconds;
 } SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
 
-PALIMPORT
-VOID
-PALAPI
-GetSystemTime(
-          OUT LPSYSTEMTIME lpSystemTime);
-
 PALIMPORT
 BOOL
 PALAPI

+ 1 - 1
pal/src/misc/time.cpp

@@ -408,7 +408,7 @@ static double CPUFreq()
     start = rdtsc();
     gettimeofday(&tstart, &tzone);
 
-    usleep(1000); // 1ms
+    usleep(2000); // 2ms
 
     end = rdtsc();
     gettimeofday(&tend, &tzone);

+ 7 - 1
test/Date/rlexe.xml

@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <regress-exe>
   <test>
     <default>
@@ -117,4 +117,10 @@
       <tags>exclude_fre,exclude_dynapogo</tags>
     </default>
   </test>
+  <test>
+    <default>
+      <files>xplatInterval.js</files>
+      <tags>exclude_jenkins,Slow</tags>
+    </default>
+  </test>
 </regress-exe>

+ 28 - 0
test/Date/xplatInterval.js

@@ -0,0 +1,28 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+// test custom GetSystemTime caching on xplat
+if (WScript.Platform && WScript.Platform.OS != "win32") {
+    function rand() {
+        return parseInt(Math.random() * 1e2) + 50;
+    }
+    for (var j = 0; j < 1e2; j++) {
+        var pre_time = Date.now(), now;
+        for(var i = 0; i < 1e6; i++) {
+            now = Date.now();
+            var diff = now - pre_time
+
+            if (diff < 0) throw new Error ("Timer interval has failed. diff < 0");
+            pre_time = now;
+        }
+
+        // wait rand time until next trial
+        for(var i = 0, to = rand(); i < to; i++) {
+            now = Date.now();
+        }
+
+        if (now < pre_time) throw new Error ("Timer interval has failed. now < pre_time");
+    }
+} // !win32