Використання Time.now
(яке повертає час настінного годинника) як базових ліній має кілька проблем, які можуть призвести до несподіваної поведінки. Це спричинено тим, що час настінного годинника може зазнавати змін, таких як вставлені високосні секунди або час повороту для налаштування місцевого часу на контрольний час.
Якщо під час вимірювання вставлена, наприклад, стрибкова секунда, вона буде вимкнена на секунду. Так само, залежно від локальних системних умов, можливо, доведеться мати справу з переходом на перехід на літній час, швидше або повільніше працюючих годинників, або навіть перехід годинника назад у часі, що призводить до негативної тривалості, та багато інших проблем.
Рішенням цього питання є використання іншого часу годинника: монотонний годинник. Цей тип годинника має інші властивості, ніж настінний. Він збільшується монітонічно, тобто ніколи не повертається назад і збільшується з постійною швидкістю. При цьому він не відображає настінний годинник (тобто час, який ви читаєте з годинника на вашій стіні), але мітку часу, яку ви можете порівняти з пізньою міткою часу, щоб отримати різницю.
У Ruby ви можете використовувати таку позначку часу з Process.clock_gettime(Process::CLOCK_MONOTONIC)
наступним чином:
t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
sleep 1.5
t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
delta = t2 - t1
delta_in_milliseconds = delta * 1000
Process.clock_gettime
Метод повертає тимчасову мітку у вигляді поплавця з часткою секунди. Фактичне число, що повертається, не має визначеного значення (на яке слід покладатися). Однак ви можете бути впевнені, що наступний дзвінок поверне більшу кількість, і, порівнявши значення, ви можете отримати реальну різницю в часі.
Ці атрибути роблять метод головним кандидатом для вимірювання різниці в часі, не бачачи, щоб ваша програма провалилася в найменш сприятливий час (наприклад, опівночі напередодні Нового року, коли буде вставлена чергова стрибкова секунда).
Process::CLOCK_MONOTONIC
Константа , яка використовується тут доступна на все сучасну Linux, BSD і систему MacOS, а також Linux підсистемі для Windows. Однак він ще не доступний для "необроблених" систем Windows. Там ви можете використовувати GetTickCount64
системний виклик, замість Process.clock_gettime
якого також повертає значення таймера в мілісекундах деталізації в Windows (> = Windows Vista, Windows Server 2008).
За допомогою Ruby ви можете викликати цю функцію так:
require 'fiddle'
GetTickCount64 = Fiddle::Function.new(
Fiddle.dlopen('kernel32.dll')['GetTickCount64'],
[],
-Fiddle::TYPE_LONG_LONG
)
timestamp = GetTickCount64.call / 1000.0