5

I wanted to get system time in nano seconds in Perl. I tried Time::HiRes module and it's supporting only until micro seconds.

brian d foy
  • 129,424
  • 31
  • 207
  • 592

5 Answers5

7

The Time::HiRes module supports up to microseconds. As @MarcoS answered in the today common hardware is nonsense to use nanosecond precision counted by software.

Two subsequent calls, getting the current microseconds and print both afterwards

perl -MTime::HiRes=time -E '$t1=time; $t2=time; printf "%.6f\n", $_ for($t1, $t2)'

results (on my system)

1411630025.846065
1411630025.846069

e.g. only getting the current time two times and nothing between costs 3-4 microseconds.

If you want some "nanosecond numbers", simply print the time with 9digit precision, like:

perl -MTime::HiRes=time -E '$t1=time;$t2=time; printf "%.9f\n", $_ for($t1, $t2)'

you will get like:

1411630910.582282066
1411630910.582283974

pretty nanosecond times ;)

Anyway, you can sleep with reasonable nanosecond precision. From the doc

nanosleep ( $nanoseconds )

Sleeps for the number of nanoseconds (1e9ths of a second) specified. Returns the number of nanoseconds actually slept (accurate only to microseconds, the nearest thousand of them).

...

Do not expect nanosleep() to be exact down to one nanosecond. Getting even accuracy of one thousand nanoseconds is good.

clt60
  • 62,119
  • 17
  • 107
  • 194
4

The time resolution depends on harwdware clock frequency, of course.
For example, an AMD 5200 has a 2.6Ghz clock, which has 0.4ns interval. The cost of gettimeofday with RDTSCP is 221 cycles: that equals 88ns at best. The minimal cost of a Perl routine will be hundreds times...

So, the final answer is:

On today's hardware, forget nano seconds. With Perl and with any high level language... You can get in that proximity just with assembler, but forget to count single nanoseconds, with software...

MarcoS
  • 17,323
  • 24
  • 96
  • 174
3

Perl get Time useing Time::HiRes

c:\Code>perl -MDateTime::HiRes -E "while (1) {say DateTime::HiRes->now()->strftime('%F %T.%N');}"

or

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";
Sakthi Karthik
  • 3,105
  • 4
  • 25
  • 29
1

The fundamental issue is that Perl's Time::HiRes uses an ordinary floating point value to represent the timestamp, usually implemented as a native C double, which on many platforms is a 64-bit IEEE float, with a 53-bit mantissa.

That means that timestamps are recorded to a resolution that varies with how far from 1970 they are:

approximate date range resolution
13 Nov 1969 ~ 18 Feb 1970 less than 0.93ns nanosecond resolution available
25 Sep 1969 ~ 08 Apr 1970 1.86ns
20 Jun 1969 ~ 14 Jul 1970 3.73ns
08 Dec 1968 ~ 24 Jan 1971 7.45ns
16 Nov 1967 ~ 16 Feb 1972 14.9ns
Jul 1961 ~ Jun 1978 29.8ns
1978~1986 & 1953~1961 59.6ns
1987~2003 & 1936~1952 0.119µs
2004~2037 & 1902~1935 0.238µs
2038~2105 & 1834~1901 0.477µs
2106~2242 & 1698~1833 0.954µs
before 1697 or after 2243 worse than microsecond resolution
Martin Kealey
  • 546
  • 2
  • 11
0

The "forget nanoseconds" people are all wrong: perl on normal machines now often returns the same microseconds in subsequent calls, so while atual nanosecond resolution might not (yet) be achievable, you absolutely do need nanoseconds now because microseconds are to coarse.

The above answers are wrong - fudging more digits from the imprecision of floats is NOT giving more precision:-

perl -MTime::HiRes=time -E 'while(1){my $now=sprintf("%.9f",time); die if($now==$last);$last=$now}'

That code does this:

Died at -e line 1.
  • The 2014 postings were right at the time, and those that were qualified by saying "today" (meaning 2014) remain historically correct; saying "all wrong" is itself wrong. That said, I agree that floating point with a 53-bit mantissa has only sufficient precision to represent changes of about 0.25µs when dealing with values around 1.52E9. – Martin Kealey Mar 04 '21 at 08:47