Как получить системное время в нано секундах в Perl?
Я хотел получить системное время в нано секундах в Perl.
Я старался Time::HiRes
Модуль и он поддерживает только до микросекунд.
Любая помощь будет принята с благодарностью.
5 ответов
Модуль Time:: HiRes поддерживает до микросекунд. Как @MarcoS ответил сегодня, обычное аппаратное обеспечение - это нонсенс в использовании наносекундной точности, подсчитываемой программным обеспечением.
Два последующих вызова, получение текущих микросекунд и распечатка обоих после
perl -MTime::HiRes=time -E '$t1=time; $t2=time; printf "%.6f\n", $_ for($t1, $t2)'
результаты (в моей системе)
1411630025.846065
1411630025.846069
например, только получение текущего времени два раза и ничего между стоит 3-4 микросекунды.
Если вам нужны "наносекундные числа", просто напечатайте время с точностью до 9 цифр, например:
perl -MTime::HiRes=time -E '$t1=time;$t2=time; printf "%.9f\n", $_ for($t1, $t2)'
вы получите как:
1411630910.582282066
1411630910.582283974
красивые наносекундные времена;)
В любом случае, вы можете спать с разумной точностью до наносекунды. Из документа
наносон (в наносекундах)
Спит для указанного количества наносекунд (1e9ths секунды). Возвращает количество фактически спавших наносекунд (с точностью до микросекунд, ближайшая тысяча из них).
...
Не ожидайте, что nanosleep() будет с точностью до одной наносекунды. Получение точности с точностью до тысячи наносекунд - это хорошо.
Разумеется, временное разрешение зависит от тактовой частоты аппаратного обеспечения.
Например, AMD 5200 имеет тактовую частоту 2,6 ГГц с интервалом 0,4 нс. Стоимость gettimeofday с RDTSCP составляет 221 цикл, что в лучшем случае равно 88 нс. Минимальная стоимость рутины Perl будет в сотни раз...
Итак, окончательный ответ:
На сегодняшнем оборудовании забудьте о нано секундах. С Perl и любым другим языком высокого уровня... Вы можете достичь этой близости просто с помощью ассемблера, но не забудьте посчитать отдельные наносекунды с помощью программного обеспечения...
Perl get Time использует Time::HiRes
c:\Code>perl -MDateTime::HiRes -E "while (1) {say DateTime::HiRes->now()->strftime('%F %T.%N');}"
или же
use Time::HiRes qw(time);
use POSIX qw(strftime);
my $t = time;
my $date = strftime "%F %T.%N", localtime $t;
$date .= sprintf ".%03d", ($t-int($t))*1000; # without rounding
print $date, "\n";
Фундаментальная проблема заключается в том, что Perl Time::HiRes использует обычное значение с плавающей запятой для представления метки времени, обычно реализованное как родной C
double
, который на многих платформах является 64-битным числом с плавающей запятой IEEE с 53-битной мантиссой.
Это означает, что метки времени записываются с разрешением, которое зависит от того, насколько они далеки от 1970 года:
Люди "забывают наносекунды" не правы: perl на обычных машинах теперь часто возвращает те же микросекунды при последующих вызовах, поэтому, хотя фактическое разрешение наносекунды может (пока) не быть достижимым, вам сейчас действительно нужны наносекунды, потому что микросекунды грубые.
Вышеприведенные ответы неверны - фальсификация большего количества цифр из-за неточностей с плавающей точкой НЕ дает большей точности:-
perl -MTime::HiRes=time -E 'while(1){my $now=sprintf("%.9f",time); die if($now==$last);$last=$now}'
Этот код делает это:
Died at -e line 1.