Clock drift on Windows

后端 未结 13 594
无人共我
无人共我 2020-12-28 18:42

I\'ve developed a Windows service which tracks business events. It uses the Windows clock to timestamp events. However, the underlying clock can drift quite dramatically (e.

相关标签:
13条回答
  • 2020-12-28 19:16

    As already mentioned, Java programs can cause this issue.

    Another solution that does not require code modification is adding the VM argument -XX:+ForceTimeHighResolution (found on the NTP support page).

    9.2.3. Windows and Sun's Java Virtual Machine

    Sun's Java Virtual Machine needs to be started with the >-XX:+ForceTimeHighResolution parameter to avoid losing interrupts.

    See http://www.macromedia.com/support/coldfusion/ts/documents/createuuid_clock_speed.htm for more information.

    From the referenced link (via the Wayback machine - original link is gone):

    ColdFusion MX: CreateUUID Increases the Windows System Clock Speed

    Calling the createUUID function multiple times under load in Macromedia ColdFusion MX and higher can cause the Windows system clock to accelerate. This is an issue with the Java Virtual Machine (JVM) in which Thread.sleep calls less than 10 milliseconds (ms) causes the Windows system clock to run faster. This behavior was originally filed as Sun Java Bug 4500388 (developer.java.sun.com/developer/bugParade/bugs/4500388.html) and has been confirmed for the 1.3.x and 1.4.x JVMs.

    In ColdFusion MX, the createUUID function has an internal Thread.sleep call of 1 millisecond. When createUUID is heavily utilized, the Windows system clock will gain several seconds per minute. The rate of acceleration is proportional to the number of createUUID calls and the load on the ColdFusion MX server. Macromedia has observed this behavior in ColdFusion MX and higher on Windows XP, 2000, and 2003 systems.

    0 讨论(0)
  • 2020-12-28 19:21

    I once wrote a Delphi class to handle time resynchs. It is pasted below. Now that I see the "w32tm" command mentioned by Larry Silverman, I suspect I wasted my time.

    unit TimeHandler;
    
    interface
    
    type
      TTimeHandler = class
      private
        FServerName : widestring;
      public
        constructor Create(servername : widestring);
        function RemoteSystemTime : TDateTime;
        procedure SetLocalSystemTime(settotime : TDateTime);
      end;
    
    implementation
    
    uses
      Windows, SysUtils, Messages;
    
    function NetRemoteTOD(ServerName :PWideChar; var buffer :pointer) : integer; stdcall; external 'netapi32.dll';
    function NetApiBufferFree(buffer : Pointer) : integer; stdcall; external 'netapi32.dll';
    
    type
      //See MSDN documentation on the TIME_OF_DAY_INFO structure.
      PTime_Of_Day_Info = ^TTime_Of_Day_Info;
      TTime_Of_Day_Info = record
        ElapsedDate : integer;
        Milliseconds : integer;
        Hours : integer;
        Minutes : integer;
        Seconds : integer;
        HundredthsOfSeconds : integer;
        TimeZone : LongInt;
        TimeInterval : integer;
        Day : integer;
        Month : integer;
        Year : integer;
        DayOfWeek : integer;
      end;
    
    constructor TTimeHandler.Create(servername: widestring);
    begin
      inherited Create;
      FServerName := servername;
    end;
    
    function TTimeHandler.RemoteSystemTime: TDateTime;
    var
      Buffer : pointer;
      Rek : PTime_Of_Day_Info;
      DateOnly, TimeOnly : TDateTime;
      timezone : integer;
    begin
      //if the call is successful...
      if 0 = NetRemoteTOD(PWideChar(FServerName),Buffer) then begin
        //store the time of day info in our special buffer structure
        Rek := PTime_Of_Day_Info(Buffer);
    
        //windows time is in GMT, so we adjust for our current time zone
        if Rek.TimeZone <> -1 then
          timezone := Rek.TimeZone div 60
        else
          timezone := 0;
    
        //decode the date from integers into TDateTimes
        //assume zero milliseconds
        try
          DateOnly := EncodeDate(Rek.Year,Rek.Month,Rek.Day);
          TimeOnly := EncodeTime(Rek.Hours,Rek.Minutes,Rek.Seconds,0);
        except on e : exception do
          raise Exception.Create(
                                 'Date retrieved from server, but it was invalid!' +
                                 #13#10 +
                                 e.Message
                                );
        end;
    
        //translate the time into a TDateTime
        //apply any time zone adjustment and return the result
        Result := DateOnly + TimeOnly - (timezone / 24);
      end  //if call was successful
      else begin
        raise Exception.Create('Time retrieval failed from "'+FServerName+'"');
      end;
    
      //free the data structure we created
      NetApiBufferFree(Buffer);
    end;
    
    procedure TTimeHandler.SetLocalSystemTime(settotime: TDateTime);
    var
      SystemTime : TSystemTime;
    begin
      DateTimeToSystemTime(settotime,SystemTime);
      SetLocalTime(SystemTime);
      //tell windows that the time changed
      PostMessage(HWND_BROADCAST,WM_TIMECHANGE,0,0);
    end;
    
    end.
    
    0 讨论(0)
  • 2020-12-28 19:22

    Sync more often. Look at the Registry entries for the W32Time service, especially "Period". "SpecialSkew" sounds like it would help you.

    0 讨论(0)
  • 2020-12-28 19:23

    Other than resynching the clock more frequently, I don't think there is much you can do, other than to get a new motherboard, as your clock signal doesn't seem to be at the right frequency.

    0 讨论(0)
  • 2020-12-28 19:23

    http://www.codinghorror.com/blog/2007/01/keeping-time-on-the-pc.html

    PC clocks should typically be accurate to within a few seconds per day. If you're experiencing massive clock drift-- on the order of minutes per day-- the first thing to check is your source of AC power. I've personally observed systems with a UPS plugged into another UPS (this is a no-no, by the way) that gained minutes per day. Removing the unnecessary UPS from the chain fixed the time problem. I am no hardware engineer, but I'm guessing that some timing signal in the power is used by the real-time clock chip on the motherboard.

    0 讨论(0)
  • 2020-12-28 19:24

    Increase the frequency of the re-sync. If the syncs are with your own main server on your own network there's no reason not to sync every minute.

    0 讨论(0)
提交回复
热议问题