Дрифт часов в Windows

Я разработал службу Windows, которая отслеживает бизнес-события. Он использует часы Windows для событий timestamp. Однако базовые часы могут резко дрейфовать (например, проигрывать несколько секунд в минуту), особенно когда CPU работают. Наши серверы используют службу времени Windows, чтобы оставаться в синхронизации с контроллерами домена, которая использует NTP под капотом, но частота синхронизации контролируется политикой домена, и в любом случае даже синхронизация каждую минуту по-прежнему допускает значительный дрейф. Существуют ли какие-либо методы, которые мы можем использовать для поддержания стабильности часов, кроме использования аппаратных часов?

Ответы

Ответ 1

Циклы часов должны быть предсказуемыми, но на большинстве аппаратных средств ПК - потому что они не предназначены для систем реального времени. Другие прерывания устройства ввода-вывода имеют приоритет перед прерыванием тактового сигнала, а некоторые драйверы выполняют обширную обработку в прерывании а не отложить его до отложенного вызова процедуры (DPC), что означает, что система не сможет обслуживать прерывание тактового сигнала до ( иногда) спустя долгое время после того, как оно было сигнализировано.

Другие факторы включают в себя контроллеры ввода-вывода с шиной, которые украшают многие циклы шины памяти из ЦП, в результате чего он задерживается в течение длительных периодов пропускной способности шины памяти.

Как говорили другие, аппаратура синхронизации часов также может изменять свою частоту по мере изменения значений компонентов с температурой.

Windows позволяет количество тиков, добавленных к часам реального времени, на каждом прерывании, которое нужно настроить: см. SetSystemTimeAdjustment. Однако это будет работать, только если у вас есть предсказуемое перекос часов. Если часы только немного отключены, SNTP-клиент (услуга "Время Windows" ) отрегулирует это перекос, чтобы сделать тактировку часов несколько быстрее или медленнее, чтобы двигаться в направлении правильного времени.

Ответ 2

Я не знаю, относится ли это, но...

В Windows возникает проблема: если вы измените разрешение таймера с timeBeginPeriod(), часы будут дрейфовать.

На самом деле, есть ошибка в реализации Java Thread wait()os::sleep()) Windows, которая вызывает это поведение. Он всегда устанавливает разрешение таймера на 1 мс перед ожиданием, чтобы быть точным (независимо от длины сна), и восстанавливает его сразу же после завершения, если только другие нити все еще не спят. Этот набор /reset будет затем путать часы Windows, который ожидает, что квант времени окна будет довольно постоянным.

Sun действительно известно об этом с 2006 года и не исправил его, AFAICT!

У нас на самом деле часы были в два раза быстрее из-за этого! Простая Java-программа, которая спит 1 миллисекунда в цикле, показывает это поведение.

Решение состоит в том, чтобы установить временное разрешение самостоятельно, на что-то низкое и сохранить его там как можно дольше. Используйте для этого время timeBeginPeriod(). (Мы устанавливаем его на 1 мс без каких-либо побочных эффектов.)

Для этих кодировок в Java более простой способ исправить это - создать поток, который спит, пока работает приложение.

Обратите внимание, что это устранит эту проблему на машине глобально, независимо от того, какое приложение является фактическим виновником.

Ответ 3

Вы можете запустить "w32tm/resync" в запланированном файле .bat задачи. Это работает на Windows Server 2003.

Ответ 4

Помимо повторной синхронизации часов чаще, я не думаю, что вы можете многое сделать, кроме как получить новую материнскую плату, так как ваш тактовый сигнал не кажется на правильной частоте.

Ответ 5

Как уже упоминалось, программы Java могут вызвать эту проблему.

Другим решением, которое не требует модификации кода, является добавление аргумента VM -XX:+ForceTimeHighResolution (найдено на странице поддержки NTP).

9.2.3. Виртуальная машина Windows и Sun Java

Виртуальная машина Sun Java должна запускаться с параметром > -XX: + ForceTimeHighResolution, чтобы избежать потери прерываний.

Для получения дополнительной информации см. http://www.macromedia.com/support/coldfusion/ts/documents/createuuid_clock_speed.htm.

Из ссылочной ссылки (через Wayback machine - исходная ссылка ушла):

ColdFusion MX: CreateUUID Увеличивает скорость работы системы Windows

Вызов функции createUUID несколько раз при загрузке в Macromedia ColdFusion MX и выше могут привести к системным часам Windows ускоряться. Это проблема с виртуальной машиной Java (JVM) в который вызывает Thread.sleep менее 10 миллисекунд (мс), вызывает Системные часы Windows работают быстрее. Это поведение было первоначально подано как Sun Java Ошибка 4500388 (developer.java.sun.com/developer/bugParade/bugs/4500388.html) и имеет было подтверждено для JVM 1.3.x и 1.4.x.

В ColdFusion MX функция createUUID имеет внутренний Thread.sleep вызов 1 миллисекунды. Когда createUUID активно используется, Системные часы Windows получат несколько секунд в минуту. Скорость ускорение пропорционально количеству вызовов createUUID и загрузить на сервер ColdFusion MX. Macromedia наблюдала это поведение в ColdFusion MX и выше в Windows XP, 2000 и 2003 годах системы.

Ответ 6

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

Часы ПК обычно должны быть точными с точностью до нескольких секунд в день. Если вы испытываете огромный дрейф часов - порядка минут в день - первое, что нужно проверить, это ваш источник питания переменного тока. Я лично наблюдал системы с ИБП, подключенными к другому ИБП (кстати, это нет-нет), которые набирали минуты в день. Извлечение ненужного ИБП из цепочки устраняет проблему времени. Я не инженер-аппаратчик, но я предполагаю, что какой-то сигнал синхронизации во власти используется чипом часов реального времени на материнской плате.

Ответ 7

Увеличьте частоту повторной синхронизации. Если синхронизация выполняется с вашим собственным основным сервером в вашей собственной сети, нет никакой причины не синхронизировать каждую минуту.

Ответ 9

Дрейф часов может быть следствием температуры; может быть, вы могли бы попытаться получить температуру более постоянной - возможно, с использованием лучшего охлаждения? Однако вы никогда не потеряете дрейф.

Использование внешних часов (GPS-приемник и т.д.) и статистический метод для связывания времени процессора с Absolute Time - это то, что мы используем здесь для синхронизации событий в распределенных системах.

Ответ 10

Поскольку это звучит так, будто у вас большой бизнес:

Возьмите старый ноутбук или что-то, что плохо для многих, но, похоже, имеет более или менее надежные часы и назовите его Timekeeper. Задача Timekeeper - это, как только каждые (скажем) 2 минуты, отправить сообщение серверам, сообщающим время. Вместо того, чтобы использовать часы Windows для своих временных меток, серверы будут отключать время от последнего сигнала Timekeeper, а также прошедшее время с момента сигнала. Проверяйте часы Timekeeper своими наручными часами один или два раза в неделю. Этого должно быть достаточно.

Ответ 11

На каких серверах вы работаете? В десктопах, когда я сталкивался с этим, с включенным FSB с расширенным спектром, возникают некоторые проблемы с синхронизацией прерываний, что и делает тактику часов. Может захотеть проверить, является ли это вариант в BIOS на одном из этих серверов и отключить его, если он включен.

Другой вариант, который вы имеете, - отредактировать интервал опроса времени и сделать его намного короче, используя следующий раздел реестра, скорее всего, вам придется его добавить (обратите внимание, что это значение DWORD, а значение - в секундах, например, 600 на 10 мин):

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient\SpecialPollInterval

Здесь полная работа над этим: KB816042

Ответ 12

Я как-то написал класс Delphi для обработки временных пересинхронов. Он вставлен ниже. Теперь, когда я вижу команду "w32tm", упомянутую Ларри Сильверманом, я подозреваю, что потерял время.

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.

Ответ 13

Я считаю, что Windows Time Service реализует только SNTP, что является упрощенной версией NTP. Полная реализация NTP учитывает стабильность ваших часов при определении того, как часто синхронизировать.

Вы можете получить полный NTP-сервер для Windows здесь.