Reputation: 291
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
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
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
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
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
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
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