为什么这些时间戳在 Perl Time::HiRes 中乱序?
Why are these timestamps out of order with Perl Time::HiRes?
我发现 Perl 的 Time::HiRes
模块报告的时间戳有一些奇怪的行为。
我有一个获取三个时间戳的脚本:
- 使用
Time::HiRes::time
获取时间戳
- 新建一个文件,修改时间为
Time::HiRes::stat
- 使用
Time::HiRes::time
获取时间戳
我希望时间戳是有序的1 < 2 < 3
,但情况并非总是如此;通常(但不总是),stat
在 2. 中报告的时间是 before 来自 1..
的时间戳
我使用的是 Ext4 文件系统。这是一个实验:
use Time::HiRes qw/ time stat /;
while( 1 ){
# t0
my $t0 = time;
# Create a file
my $f = '/tmp/dummy.test';
open(my $fh, '>', $f) || die;
print $fh "hi\n";
close($fh) || die;
# FS: file modification time, according to the filestystem
my $fs = (stat($f))[9];
# t1
my $t1 = time;
## Report how the timestamps relate to each other
# A. All good
if( $t0 < $fs && $fs < $t1 ){
print "$t1,0\n";
}
# B. FS before t0
elsif( $t0 > $fs && $fs < $t1 ){
print "$t1,1\n";
}
# C. FS after t1
elsif( $t0 < $fs && $fs > $t1 ){
print "$t1,2\n";
}
# D. this should never happen (t0 and t1 probably can't flip)
elsif( $t0 > $fs && $fs > $t1 ){
print "$t1,3\n";
}
}
下面是让上面的循环 运行 几秒钟的结果。底部的蓝点是 "correct" 行为的事件。通常情况下,我得到条件 B
,其中 stat
的修改时间是 在 第一个时间戳之前。
什么可以解释这种行为?
更新: 这是前 2000 次迭代的时间戳滞后图:
这可能是因为文档中提到的两个时间戳的精度不同 here:
As stat or lstat but
with the access/modify/change file timestamps in subsecond resolution,
if the operating system and the filesystem both support such
timestamps. To override the standard stat():
use Time::HiRes qw(stat);
Test for the value of &Time::HiRes::d_hires_stat to find out whether the operating system
supports subsecond file timestamps: a value larger than zero means
yes. There are unfortunately no easy ways to find out whether the
filesystem supports such timestamps. UNIX filesystems often do; NTFS
does; FAT doesn't (FAT timestamp granularity is two seconds).
A zero
return value of &Time::HiRes::d_hires_stat means that
Time::HiRes::stat is a no-op passthrough for CORE::stat() (and
likewise for lstat), and therefore the timestamps will stay integers.
The same thing will happen if the filesystem does not do subsecond
timestamps, even if the &Time::HiRes::d_hires_stat is non-zero.
In any
case do not expect nanosecond resolution, or even a microsecond
resolution. Also note that the modify/access timestamps might have
different resolutions, and that they need not be synchronized, e.g. if
the operations are
write
stat # t1
read
stat # t2
the access time stamp from t2 need not be greater-than the modify
time stamp from t1: it may be equal or less.
我发现 Perl 的 Time::HiRes
模块报告的时间戳有一些奇怪的行为。
我有一个获取三个时间戳的脚本:
- 使用
Time::HiRes::time
获取时间戳
- 新建一个文件,修改时间为
Time::HiRes::stat
- 使用
Time::HiRes::time
获取时间戳
我希望时间戳是有序的1 < 2 < 3
,但情况并非总是如此;通常(但不总是),stat
在 2. 中报告的时间是 before 来自 1..
我使用的是 Ext4 文件系统。这是一个实验:
use Time::HiRes qw/ time stat /;
while( 1 ){
# t0
my $t0 = time;
# Create a file
my $f = '/tmp/dummy.test';
open(my $fh, '>', $f) || die;
print $fh "hi\n";
close($fh) || die;
# FS: file modification time, according to the filestystem
my $fs = (stat($f))[9];
# t1
my $t1 = time;
## Report how the timestamps relate to each other
# A. All good
if( $t0 < $fs && $fs < $t1 ){
print "$t1,0\n";
}
# B. FS before t0
elsif( $t0 > $fs && $fs < $t1 ){
print "$t1,1\n";
}
# C. FS after t1
elsif( $t0 < $fs && $fs > $t1 ){
print "$t1,2\n";
}
# D. this should never happen (t0 and t1 probably can't flip)
elsif( $t0 > $fs && $fs > $t1 ){
print "$t1,3\n";
}
}
下面是让上面的循环 运行 几秒钟的结果。底部的蓝点是 "correct" 行为的事件。通常情况下,我得到条件 B
,其中 stat
的修改时间是 在 第一个时间戳之前。
什么可以解释这种行为?
更新: 这是前 2000 次迭代的时间戳滞后图:
这可能是因为文档中提到的两个时间戳的精度不同 here:
As stat or lstat but with the access/modify/change file timestamps in subsecond resolution, if the operating system and the filesystem both support such timestamps. To override the standard stat():
use Time::HiRes qw(stat);
Test for the value of &Time::HiRes::d_hires_stat to find out whether the operating system supports subsecond file timestamps: a value larger than zero means yes. There are unfortunately no easy ways to find out whether the filesystem supports such timestamps. UNIX filesystems often do; NTFS does; FAT doesn't (FAT timestamp granularity is two seconds).
A zero return value of &Time::HiRes::d_hires_stat means that Time::HiRes::stat is a no-op passthrough for CORE::stat() (and likewise for lstat), and therefore the timestamps will stay integers. The same thing will happen if the filesystem does not do subsecond timestamps, even if the &Time::HiRes::d_hires_stat is non-zero.
In any case do not expect nanosecond resolution, or even a microsecond resolution. Also note that the modify/access timestamps might have different resolutions, and that they need not be synchronized, e.g. if the operations are
write stat # t1 read stat # t2
the access time stamp from t2 need not be greater-than the modify time stamp from t1: it may be equal or less.