Я разработал службу Windows, которая отслеживает деловые события. Он использует часы Windows для отметки времени событиями. Однако базовые часы могут довольно сильно дрейфовать (например, терять несколько секунд в минуту), особенно когда процессоры усердно работают. Наши серверы используют службу времени Windows, чтобы оставаться в синхронизации с контроллерами домена, которые используют NTP под капотом, но частота синхронизации контролируется политикой домена, и в любом случае даже ежеминутная синхронизация по-прежнему допускает значительный дрейф. Есть ли какие-либо методы, которые мы можем использовать, чтобы часы оставались более стабильными, кроме использования аппаратных часов?
Похоже, это вопрос, связанный с программированием
Дрейф часов на несколько секунд в минуту - это сломанные часы, независимо от того, насколько сильно машина работает. Вам нужно новое оборудование.
Вы не должны получать несколько секунд каждую минуту. Что-то не так с часами. Или у вас есть две программные службы, которые играют со временем на машине и меняют его из разных источников?
Возможно, вы столкнулись с проблемой Microsoft Minute.





Помимо более частой повторной синхронизации часов, я не думаю, что вы можете что-то сделать, кроме как приобрести новую материнскую плату, поскольку ваш тактовый сигнал, похоже, не находится на нужной частоте.
Увеличьте частоту повторной синхронизации. Если синхронизация выполняется с вашим собственным главным сервером в вашей сети, нет причин не синхронизировать каждую минуту.
Синхронизируйте чаще. Посмотрите на Записи реестра для службы W32Time, особенно на «Период». "SpecialSkew" звучит так, как будто это поможет вам.
Дрейф часов может быть следствием температуры; Может быть, вы могли бы попытаться получить более постоянную температуру - возможно, используя лучшее охлаждение? Однако вы никогда не потеряете дрейф полностью.
Использование внешних часов (приемник GPS и т. д.) И статистический метод для связи времени процессора с абсолютным временем - это то, что мы используем здесь для синхронизации событий в распределенных системах.
Какие серверы у вас установлены? На настольных компьютерах я сталкивался с этим, когда включили Spread Spectrum FSB, что вызывает некоторые проблемы с синхронизацией прерывания, которая заставляет эти часы тикать. Возможно, вам захочется узнать, есть ли эта опция в BIOS на одном из этих серверов, и выключить ее, если она включена.
Другой вариант, который у вас есть, - отредактировать интервал опроса и сделать его намного короче с помощью следующего раздела реестра, скорее всего, вам придется его добавить (обратите внимание, что это значение DWORD, а значение указано в секундах, например 600 для 10 минут) :
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient\SpecialPollInterval
Вот полная работа над этим: KB816042
Вы можете запустить «w32tm / resync» в файле .bat запланированной задачи. Это работает в Windows Server 2003.
Однажды я написал класс 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.
Я считаю, что служба времени Windows реализует только SNTP, который является упрощенной версией NTP. Полная реализация NTP принимает во внимание стабильность ваших часов при принятии решения о том, как часто выполнять синхронизацию.
Вы можете получить полный NTP-сервер для Windows здесь.
Windows 2000 была последней версией, которая все еще использовала SNTP technet.microsoft.com/en-us/library/…
Такты часов должны быть предсказуемыми, но на большинстве аппаратных средств ПК - потому что они не предназначены для систем реального времени - прерывания других устройств ввода-вывода имеют приоритет над прерываниями тактов, а некоторые драйверы выполняют обширную обработку в подпрограмме обслуживания прерываний. чем отложить его до отложенный вызов процедуры (DPC), что означает, что система может быть не в состоянии обслуживать прерывание по тактовому сигналу до (иногда) долгого времени после того, как о нем поступил сигнал.
К другим факторам относятся управляющие шиной контроллеры ввода-вывода, которые отбирают у ЦП много циклов шины памяти, в результате чего ему не хватает пропускной способности шины памяти в течение значительных периодов времени.
Как уже говорили другие, оборудование для генерации часов также может изменять свою частоту, поскольку значения компонентов меняются с температурой.
Windows позволяет регулировать количество тактов, добавляемых к часам реального времени при каждом прерывании: см. SetSystemTimeAdjustment. Однако это сработает только в том случае, если у вас будет предсказуемый сдвиг часов. Если часы немного отклоняются, клиент SNTP (служба «Время Windows») отрегулирует этот перекос, чтобы часы тикали немного быстрее или медленнее, чтобы приблизиться к правильному времени.
Не знаю, применимо ли это, но ...
В Windows есть проблема, заключающаяся в том, что если вы сильно измените разрешение таймера с помощью timeBeginPeriod (), часы будут дрейфовать.
На самом деле, в реализации Windows функции Java Thread wait() (и os::sleep()) есть ошибка, которая вызывает такое поведение. Он всегда устанавливает разрешение таймера на 1 мс перед ожиданием, чтобы быть точным (независимо от продолжительности сна), и восстанавливает его сразу после завершения, если другие потоки все еще не спят. Этот набор / сброс затем запутает часы Windows, которые ожидают, что квант времени Windows будет довольно постоянным.
Sun на самом деле имеет известно об этом с 2006 года и не исправляет его, AFAICT!
На самом деле из-за этого часы шли вдвое быстрее! Это поведение демонстрирует простая программа на Java, которая выполняет цикл на 1 миллисекунду.
Решение состоит в том, чтобы самостоятельно установить временное разрешение на что-нибудь низкое и поддерживать его как можно дольше. Используйте timeBeginPeriod (), чтобы контролировать это. (Мы установили его на 1 мс без каких-либо побочных эффектов.)
Для тех, кто кодирует на Java, более простой способ исправить это - создать поток, который бездействует, пока существует приложение.
Обратите внимание, что это устранит эту проблему на компьютере глобально, независимо от того, какое приложение является фактической причиной.
Ух ты. Я теряю несколько ЧАСОВ в день и много работаю с Java ...
@ deed02392: Кажется, время идет медленнее, когда вы работаете с Java. Это как застрять в 90-х. ;-п
Вопрос: Применимо ли это только к java, или Delphi или C# могут вызывать аналогичные проблемы, когда много возятся с таймерами?
@Vincent: относится к любому приложению Windows, которое часто и часто вызывает timeBeginPeriod () с разными значениями.
Поскольку похоже, что у вас большой бизнес:
Возьмите старый ноутбук или что-то, что не годится для многих, но, кажется, имеет более или менее надежные часы, и назовите его хронометристом. Единственная задача хронометриста - один раз каждые (скажем) 2 минуты посылать на серверы сообщение, указывающее время. Вместо того, чтобы использовать часы Windows для своих отметок времени, серверы будут записывать время с последнего сигнала хронометриста плюс время, прошедшее с момента сигнала. Проверяйте часы хронометриста по наручным часам один или два раза в неделю. Этого должно хватить.
Как уже упоминалось, эту проблему могут вызывать программы Java.
Другое решение, не требующее модификации кода, - это добавление аргумента виртуальной машины -XX:+ForceTimeHighResolution (находится в Страница поддержки NTP).
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.
Из указанной ссылки (через Машина Wayback - исходная ссылка исчезла):
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.
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.
На самом деле это не вопрос, связанный с программированием, поэтому я не уверен, принадлежит ли он к StackOverflow.