2016-09-22 18 views
5

Я вижу странное поведение с отметкой времени, указанной модулем Perl Time::HiRes.Почему эти временные метки не работают с Perl Time :: HiRes?

У меня есть сценарий, который получает три временные метки:

  1. Get временной метки с Time::HiRes::time
  2. Создать новый файл, и получить его время модификации с Time::HiRes::stat
  3. Получить временную метку с Time::HiRes::time

Я бы ожидал, что отметки времени будут заказаны 1 < 2 < 3, однако это не всегда так; часто (но не всегда), время, указанное stat в 2., равно до временная метка от 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"; 
    } 
} 

Вот результаты пуска вышеуказанного цикла в течение нескольких секунд. где синие точки на дне являются инцидентами «правильного» поведения. Чаще всего я получаю условие B, где время модификации от stat составляет до первая метка времени.

enter image description here

Что может объяснить такое поведение?

Update: Вот сюжет из метки времени запаздывания для кулака 2000 итераций:

enter image description here

+0

'$ t0- $ fs," ", $ t1- $ fs' показывают, что как $ t0, так и $ t1 очень близки друг к другу и намного опережают $ fs –

ответ

5

Это может быть из-за разницы в точности как метки времени, как указано в док here:

Как стат или lstat но с доступом/изменить/изменить временные метки файлов в субсекундном разрешении, если опера ting и файловая система поддерживают такие отметки времени . Для того, чтобы изменить стандартный стат():

use Time::HiRes qw(stat); 

тест для значения & Time :: HiRes :: d_hires_stat, чтобы выяснить, поддерживает ли операционная система метку время субсекундного файла: значение больше нуля означает да. К сожалению, нет простых способов узнать, поддерживает ли файловая система такие временные метки. Файловые системы UNIX часто делают; NTFS делает; FAT нет (гранулярность временной шкалы FAT равна два секунд).

Нулевое возвращаемое значение & Time :: HiRes :: d_hires_stat означает, что Время :: HiRes :: стат не-оп передачу для CORE :: стат() (и аналогично для lstat), и поэтому метки времени будут оставаться целыми. То же самое произойдет, если файловая система не делает subsecond временных меток, даже если значение & Time :: HiRes :: d_hires_stat отличное от нуля.

В любом случае корпус не должен наноситься наносекундным разрешением или даже разрешением микросекунды . Также обратите внимание, что временные метки изменения/доступа могут иметь разных разрешений и что их не нужно синхронизировать, например. если операции являются

write 
stat # t1 
read 
stat # t2 

время доступа штамп из t2 не должен быть больше, чем изменение штампа времени от t1: она может быть равна или меньше .