Perl でシステム時間をナノ秒単位で取得したかったのです。モジュールを試してみTime::HiRes
ましたが、マイクロ秒までしかサポートしていません。
5 に答える
Time::HiResモジュールはマイクロ秒までサポートします。今日の一般的なハードウェアで@MarcoSが答えたように、ソフトウェアによってカウントされるナノ秒の精度を使用するのはナンセンスです。
2 つの後続の呼び出し、現在のマイクロ秒を取得し、その後両方を出力します。
perl -MTime::HiRes=time -E '$t1=time; $t2=time; printf "%.6f\n", $_ for($t1, $t2)'
結果(私のシステム上)
1411630025.846065
1411630025.846069
たとえば、現在の時刻を 2 回取得するだけで、3 ~ 4 マイクロ秒のコストがかかります。
「ナノ秒の数値」が必要な場合は、次のように 9 桁の精度で時刻を出力するだけです。
perl -MTime::HiRes=time -E '$t1=time;$t2=time; printf "%.9f\n", $_ for($t1, $t2)'
あなたは次のようになります:
1411630910.582282066
1411630910.582283974
かなりナノ秒です;)
とにかく、妥当なナノ秒の精度で眠ることができます。ドキュメントから
ナノスリープ ( $nanoseconds )
指定されたナノ秒 (1e9 秒) の間スリープします。実際にスリープ状態になったナノ秒数を返します (マイクロ秒単位まで正確であり、1,000 に最も近い単位です)。
...
nanosleep() が 1 ナノ秒まで正確であるとは思わないでください。1000ナノ秒の精度さえ得られるのは良いことです。
Perl は 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 float で、53 ビットの仮数部があります。
つまり、タイムスタンプは、1970 年からの距離に応じて異なる解像度で記録されます。
おおよその日付範囲 | 解像度 | ||
---|---|---|---|
1969年11月13日~1970年2月18日 | 0.93ns未満 | ナノ秒の分解能が利用可能 | |
1969年9月25日 ~ 1970年4月8日 | 1.86ns | ||
1969年6月20日~1970年7月14日 | 3.73ns | ||
1968年12月08日 ~ 1971年1月24日 | 7.45ns | ||
1967年11月16日 ~ 1972年2月16日 | 14.9ns | ||
1961年7月~1978年6月 | 29.8ns | ||
1978~1986 & 1953~1961 | 59.6ns | ||
1987~2003 & 1936~1952 | 0.119μs | ||
►</td> | 2004~2037 & 1902~1935 | 0.238μs | ◄</td> |
2038~2105 & 1834~1901 | 0.477μs | ||
2106~2242 & 1698~1833 | 0.954μs | ||
1697年以前または2107年以降 | マイクロ秒の解像度より悪い |