Каков правильный способ точно измерить продолжительность времени в Go? В большинстве приложений используется стандартный пакет времени и следующий подход:
var startTime = time.Now()
doSomeHardWork()
var duration = time.Since(startTime) // or: time.Now() - startTime
Однако time.Now() возвращает текущее системное время, что приводит к двум недостаткам:
- Если системное время изменяется во время измерения (например, из-за изменения часового пояса (DST) или прыжок второй), результирующая продолжительность также неверна.
-
Системное время может зацикливаться быстрее или медленнее, чем в реальном времени. Это всегда происходит, когда операционная система синхронизирует внутренние часы с серверами времени NTP (что может происходить несколько раз в час!)
От MSDN:
[Служба времени] настраивает локальную тактовую частоту, чтобы сходятся к правильному времени. Если разница во времени между локальные часы и [точный отсчет времени] слишком велики, чтобы настраивая местную тактовую частоту, служба времени устанавливает локальные часы на правильное время.
Если системное время изменяется (вручную или из-за DST), возможно, будет обнаружена недействительная продолжительность и отброшена. Но если системные часы гаснут, например. На 10% быстрее синхронизироваться с мировым временем, его практически невозможно обнаружить. Это предполагаемое поведение и способы создания системных часов.
По этой причине большинство других языков предлагают специальный API для измерения продолжительности:
- Java имеет
System.nanoTime(),System.currentTimeMillis()будет эквивалентенtime.Now()и ошибочен - С# имеет
System.Diagnostics.Stopwatch - C/С++ в Windows
QueryPerformanceCounterиQueryPerformanceFrequency - С++ 11 и выше
std::chrono::steady_clockилиstd::chrono::high_resolution_clock, когда константа членаis_steadyравнаtrue - JavaScript имеет
performance.now(), а использованиеnew Date()неверно
Каков правильный способ точно измерить время выполнения в Go?