Использование обычного старого timeGetTime()
для измерения времени ненадежно во многих операционных системах на базе Windows, поскольку гранулярность системного таймера может достигать 10-15 миллисекунд, а это означает, что timeGetTime()
имеет точность только до 10-15 миллисекунд. [Обратите внимание, что высокая степень детализации наблюдается в операционных системах на базе NT, таких как Windows NT, 2000 и XP. Windows 95 и 98, как правило, имеют гораздо лучшую гранулярность, около 1-5 мс.]
Однако, если вы вызовете timeBeginPeriod(1)
в начале вашей программы (и timeEndPeriod(1)
в конце), timeGetTime()
обычно станет точным до 1-2 миллисекунд и предоставит вам чрезвычайно точную информацию о времени.
Sleep()
ведет себя аналогично; продолжительность времени, в течение которого Sleep()
фактически спит, идет рука об руку с гранулярностью timeGetTime()
, поэтому после вызова timeBeginPeriod(1)
один раз Sleep(1)
фактически будет спать в течение 1-2 миллисекунд, Sleep(2)
в течение 2-3 и так далее (вместо того, чтобы спать с шагом 10-15 мс).
Для более высокой точности синхронизации (с точностью до миллисекунды) вам, вероятно, следует избегать использования мнемоники сборки RDTSC, поскольку ее сложно откалибровать; вместо этого используйте QueryPerformanceFrequency
и QueryPerformanceCounter
, точность которых составляет менее 10 микросекунд (0,00001 секунды).
Для простой синхронизации хорошо работают как timeGetTime, так и QueryPerformanceCounter, а QueryPerformanceCounter, очевидно, более точен. Однако, если вам нужно делать какие-либо «временные паузы» (например, необходимые для ограничения частоты кадров), вам нужно быть осторожным, чтобы не сидеть в цикле, вызывая QueryPerformanceCounter, ожидая, пока он достигнет определенного значения; это съест 100% вашего процессора. Вместо этого рассмотрите гибридную схему, в которой вы вызываете Sleep(1) (не забудьте сначала timeBeginPeriod(1)!) всякий раз, когда вам нужно передать более 1 мс времени, а затем только входите в цикл QueryPerformanceCounter со 100% занятостью для завершайте последнюю ‹ 1/1000-й секунды задержки, которая вам нужна. Это даст вам сверхточные задержки (с точностью до 10 микросекунд) при минимальном использовании ЦП. См. код выше.