Relógio à deriva nas janelas

Desenvolvi um serviço Windows que acompanha eventos empresariais. Ele usa o relógio do Windows para eventos do timestamp. No entanto, o relógio subjacente pode derivar dramaticamente (por exemplo, perder alguns segundos por minuto), particularmente quando os CPUs estão trabalhando duro. Nossos servidores usam o serviço Windows Time para ficar em sincronia com controladores de domínio, que usa NTP sob o capô, mas a frequência de sincronização é controlada pela Política de domínio, e em qualquer caso, mesmo sincronizando a cada minuto ainda permitiria deriva significativa. Há alguma técnica que possamos usar para manter o relógio mais estável, além de usar relógios de hardware?

Author: Matt Howells, 2008-09-19

13 answers

Relógio carrapatos deve ser previsível, mas na maioria do hardware do PC - porque eles não são projetados para sistemas de tempo real - outro dispositivo de e/S interrupções têm prioridade sobre o relógio tick interrupt (interrupção, e alguns drivers de fazer uma extensa transformação na rotina de serviço de interrupção, em vez de remetê-la para um chamada de procedimento deferidas (DPC), o que significa que o sistema pode não ser capaz de servir o clock tick interrupt (interrupção até que (às vezes) muito tempo depois ele foi sinalizado.

Outros factores incluem controladores de I/O que roubam muitos ciclos de barramento de memória da CPU, fazendo com que ela seja carente de largura de banda de barramento de memória por períodos significativos.

Como outros já disseram, o hardware de geração de relógios também pode variar a sua frequência à medida que os valores dos componentes mudam com a temperatura.

O Windows permite ajustar a quantidade de carrapatos adicionados ao relógio em tempo real em cada interrupção: ver ajuste de tempo do sistema Set. Isto só funcionaria se tivesses um relógio previsível, entanto. Se o relógio estiver apenas ligeiramente desligado, o cliente SNTP (Serviço"tempo do Windows") irá ajustar este desvio para fazer o relógio marcar um pouco mais rápido ou mais lento para a tendência para o tempo correto.

 17
Author: Mike Dimmick, 2008-09-19 15:33:04
Não sei se isto se aplica, mas ... ..

Há um problema com o Windows que se você mudar a resolução do temporizador com o período de tempo() muito, o relógio irá rodar.

Na verdade, existe um bug no tópico de Java {[[0]} (e na implementação do Windows da função os::sleep() que causa este comportamento. Ele sempre configura a resolução do temporizador para 1 ms antes de esperar, a fim de ser preciso (independentemente do comprimento de latência), e restaura-lo imediatamente após a conclusão, a menos que qualquer outros fios ainda estão a dormir. Este conjunto / reset irá então confundir o relógio do Windows, que espera que o tempo quântico do windows seja bastante constante.

A Sun tem realmente conhecimento disto desde 2006 {[[7]}, e não o consertou, em nada!

Tínhamos o relógio a andar duas vezes mais rápido por causa disto! Um simples programa Java que dorme 1 milisec em um loop mostra este comportamento.

A solução é definir a resolução do tempo você mesmo, para algo baixo, e mantê-lo lá o máximo possível. Usar o período de tempo () para controlar isso. (Nós ajustamos para 1 ms sem quaisquer efeitos adversos.)

Para aqueles que codificam em Java, a maneira mais fácil de corrigir isso é criando um thread que dorme enquanto o aplicativo vive.

Note que isso vai corrigir este problema na máquina globalmente, independentemente de qual aplicação é o verdadeiro culpado.

 11
Author: Macke, 2014-12-08 08:42:36

Você poderia executar "w32tm / resync" em uma tarefa agendada .bat file. Isto funciona no Windows Server 2003.

 5
Author: Larry Silverman, 2008-09-19 14:19:54
Para além de reiniciar o relógio com mais frequência, acho que não há muito que possas fazer, a não ser arranjar uma nova placa-mãe, pois o sinal do teu relógio não parece estar na frequência certa.
 4
Author: TraumaPony, 2008-09-19 14:09:18

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

Os relógios PC devem ter uma precisão de alguns segundos por dia. Se você está experimentando uma grande deriva de relógio-- na ordem de minutos por dia-- a primeira coisa a verificar é sua fonte de energia AC. Eu observei pessoalmente sistemas com um UPS plugado em outros UPS (este é um Não-Não, a propósito) que ganhou minutos por dia. Removendo os UPS desnecessários da cadeia consertou o problema de tempo. Não sou engenheiro de hardware, mas acho que algum sinal de tempo no poder é usado pelo chip do relógio em tempo real na placa-mãe.

 2
Author: Sam Greenhalgh, 2012-02-12 21:18:01

Como já mencionado, os programas Java podem causar este problema.

Outra solução que não necessita de modificação de código é adicionar o argumento VM -XX:+ForceTimeHighResolution (encontrado na página de suporte NTP).

9.2.3. Windows and Sun's Java Virtual Machine

A máquina virtual Java do Sun precisa de ser iniciada com o parâmetro >-XX:+forçar a alta resolução para evitar a perda de interrupções.

Ver http://www.macromedia.com/support/coldfusion/ts/documents/createuuid_clock_speed.htm para mais informações.

A partir da ligação referenciada (através da máquina Wayback - a ligação original desapareceu):

ColdFusion MX: CreateUUID aumenta a velocidade do relógio do sistema Windows

Chamando a função createUUID várias vezes sob carga em Macromedia ColdFusion MX e superior pode causar o relógio do sistema Windows acelerar. Este é um problema com a máquina virtual Java (JVM) em que Fio.as chamadas de sono inferiores a 10 milisegundos (ms) causam a Relógio do sistema Windows para correr mais rápido. Este comportamento foi originalmente arquivado como Sun Java Bug 4500388 (developer.java.sun.com/developer/bugParade/bugs/4500388.html) e tem confirmado para o 1.3.x e 1.4.X JVMs.

Na ColdFusion MX, a função createUUID tem uma linha interna.sono chamada de 1 milissegundo. Quando o createUUID é fortemente utilizado, o Relógio do sistema Windows vai ganhar vários segundos por minuto. A taxa de a aceleração é proporcional ao número de chamadas createUUID e ao carrega no servidor MX ColdFusion. Macromedia observou este comportamento em ColdFusion MX e superior no Windows XP, 2000, e 2003 sistema.

 2
Author: seeker, 2017-06-14 12:32:51
Aumenta a frequência da re-sincronização. Se os syncs estão com seu próprio servidor principal em sua própria rede, não há razão para não sincronizar a cada minuto.
 1
Author: Martin Beckett, 2008-09-19 14:10:08
Sincronia mais vezes. Veja as entradas do registro para o serviço W32Time , especialmente "período". "Especialskew" parece que te ajudaria.
 1
Author: Tomalak, 2008-09-19 14:11:11
A deriva do relógio pode ser uma consequência da temperatura, talvez você possa tentar obter uma temperatura mais constante - usando melhor resfriamento, talvez? Mas nunca vais perder o controlo.

Usando um relógio externo (receptor GPS, etc...), e um método estatístico para relacionar o tempo de CPU com o tempo absoluto é o que usamos aqui para sincronizar eventos em sistemas distribuídos.

 1
Author: xtofl, 2008-09-19 14:13:23
Já que parece que tens um grande negócio ... Pegue um laptop velho ou algo que não é bom para muito, mas parece ter um relógio mais ou menos confiável, e chame-lhe o cronómetro. O único trabalho do Cronometrista é, uma vez a cada (digamos) 2 minutos, Enviar uma mensagem para os servidores dizendo as horas. Em vez de usar o relógio do Windows para suas datas, os servidores irão colocar o tempo a partir do último sinal do Cronómetro, mais o tempo decorrido desde o sinal. Verifique a Relógio de cronómetro ao pé do relógio de pulso uma ou duas vezes por semana. Isto deve ser suficiente.
 1
Author: Robert L, 2009-09-04 08:51:22
Que servidores estão a executar? Em desktops as vezes que eu me deparei com isso são com Spread Spectrum FSB habilitado, causa alguns problemas com o tempo de interrupção que é o que faz aquele relógio tick. Pode querer ver se esta é uma opção em BIOS em um desses servidores e desligá-lo se ativado.

Outra opção que você tem é editar o intervalo de tempo de votação e torná-lo muito mais curto usando a seguinte chave de registro, o mais provável é que você terá que adicioná-lo (note que este é um valor DWORD e o valor é em segundos, por exemplo 600 para 10min):

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient\SpecialPollInterval
Aqui está um trabalho completo.: KB816042
 0
Author: Nick Craver, 2008-09-19 14:13:56
Uma vez escrevi uma classe Delphi para lidar com resynchs temporais. Está colado abaixo. Agora que vejo o comando "w32tm" mencionado por Larry Silverman, suspeito que perdi o meu tempo.
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
Author: JosephStyons, 2008-09-19 14:39:02

Eu acredito que o Windows Time Service apenas implementa o SNTP, que é uma versão simplificada do NTP. Uma implementação NTP completa leva em conta a estabilidade do seu relógio para decidir com que frequência sincronizar.

Pode obter o servidor NTP completo para o Windows aqui .

 0
Author: cjm, 2008-09-19 15:17:04