How to get system time in nano seconds in Perl?

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

Upvotes: 6

Views: 5280

Answers (6)

Hubert Kario
Hubert Kario

Reputation: 22880

As others already mentioned, any timer that returns a full UNIX epoch date as a floating point number is useless for sub-microsecond resolution measurements.

While the Linux clock_gettime supports a lot of different clock types, using their names in perl is useless too. Even if I specify CLOCK_BOOTTIME I still end up with result that's CLOCK_REALTIME.

Thankfully, it's possible to specify the parameter as integer too, so a call like

my $t0 = clock_gettime(2);

Will set the t0 to the current value of CLOCK_PROCESS_CPUTIME_ID timer. Quick tests also suggest that it does provide nanosecond resolution on my system.

The other one that's likely to be fairly precise is the CLOCK_BOOTTIME (int id of 7), but that will be less and less precise as the system uptime increases.

So, the real fix would be to change the clock_gettime so that it can return the current seconds and current nanoseconds as a pair of integers (just like the gettimeofday can).

Upvotes: 0

Martin Kealey
Martin Kealey

Reputation: 697

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

Upvotes: 2

user6528451
user6528451

Reputation:

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.

Upvotes: 1

clt60
clt60

Reputation: 63974

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.

Upvotes: 6

Sakthi Karthik
Sakthi Karthik

Reputation: 3169

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";

Upvotes: 1

MarcoS
MarcoS

Reputation: 17721

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...

Upvotes: 3

Related Questions