Каков правильный способ точно измерить продолжительность времени в 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?