Стоимость проверок времени модификации файла

#php #performance #filemtime

#php #Производительность #filemtime

Вопрос:

Для файла, содержащего несколько байт под Linux, мне нужно только обработать, когда он был изменен с момента последней обработки. Я проверяю, был ли изменен файл, периодически вызывая PHP clearstatcache(); filemtime(); . Поскольку весь файл всегда будет крошечным, улучшит ли производительность удаление вызова filemtime и проверка изменения файла путем сравнения содержимого с предыдущим содержимым? Или каков наилучший метод для этого с точки зрения производительности.

Комментарии:

1. Я думаю, что очень, очень вряд ли. filemtime() доступ к низкоуровневым системным функциям, которые всегда будут опережать фактическое его открытие. Интересно услышать, что говорят эксперты по файловой системе / операционной системе

2. вероятно, зависит от операционной системы и типа файловой системы. профилируйте оба и посмотрите, какой из них работает лучше в ваших конкретных настройках.

3. @Mat — Я не могу представить файловую систему, которая возвращает содержимое файла быстрее, чем метаданные … и если он есть, я не думаю, что захотел бы его использовать.

4. @Brian: данные и метаданные будут кэшироваться, если к файлу часто обращаются — разницу во времени между простым копированием метаданных в пространство пользователя и копированием нескольких байт данных файла, вероятно, трудно измерить в современной системе. Если это действительно крошечное значение, сравнение может быть таким же дешевым, как сравнение с временными метками — даже потенциально дешевле, если временные метки имеют длину 64 бита в 32-битной системе. (но могут преобладать накладные расходы на системный вызов, так что …)

5. @Mat — о, я согласен, вопрос сам по себе глуп, учитывая неизмеримые различия. Однако, если файл изменится, то кэш потребуется обновить. И я бы поспорил, что время поиска на диске устраняет любую проблему, связанную с 64-битным числом. На этот разговор ушло больше времени, чем любая «оптимизация» здесь сэкономила бы за годы 😀

Ответ №1:

Использование filemtime clearstatcache

Для улучшения теста @Ben_D:

 <?php

$file = 'small_file.html';
$loops = 1000000;

// filesize (fast)
$start_time = microtime(1);
for ($i = 0; $i < $loops; $i  ) {
    $file_size = filesize($file);
}
$end_time = microtime(1);
$time_for_file_size = $end_time - $start_time;

// filemtime (fastest)
$start_time = microtime(1);
for ($i = 0; $i < $loops; $i  ) {
    $file_mtime = filemtime($file);
}
$end_time = microtime(1);
$time_for_filemtime = $end_time - $start_time;

// filemtime   no cache (fast and reliable)
$start_time = microtime(1);
for ($i = 0; $i < $loops; $i  ) {
    clearstatcache();
    $file_mtime_nc = filemtime($file);
}
$end_time = microtime(1);
$time_for_filemtime_nc = $end_time - $start_time;

// file_get_contents  (slow and reliable)
$start_time = microtime(1);
for ($i = 0; $i < $loops; $i  ) {
    $file_contents = file_get_contents($file);
}
$end_time = microtime(1);
$time_for_file_get_contents = $end_time - $start_time;

// output
echo "
<p>Working on file '$file'</p>
<p>Size: $file_size B</p>
<p>last modified timestamp: $file_mtime</p>
<p>file contents: $file_contents</p>

<h1>Profile</h1>
<p>filesize: $time_for_file_size</p>
<p>filemtime: $time_for_filemtime</p>
<p>filemtime   no cache: $time_for_filemtime_nc</p>
<p>file_get_contents: $time_for_file_get_contents</p>";

/* End of file */
  

Результаты

Комментарии:

1. Пожалуйста, обратите внимание, что вам нужно звонить только в том случае, clearstatcache(); если вам нужна свежая filemtime информация из одного и того же файла несколько раз во время одного и того же запроса (и если предоставляется возможность, что файл может быть изменен во время запроса). filemtime кэш теряется после завершения запроса.

Ответ №2:

Я знаю, что опаздываю на вечеринку, но небольшой сравнительный анализ никогда не повредит обсуждению. Интуиция Брайана Роуча подтверждает это еще до того, как вы примете во внимание этап сравнения:

Тест:

 $file = "small_file.html";
$file_size = filesize($file);

//get the filemtime 1,000,000 times
$start_time = microtime(true);
for($i=0;$i<1000000;$i  ){
    $set_time = filemtime($file);
}
$end_time = microtime(true);

$time_for_filemtime = ($end_time-$start_time);

//get the time for file_get_contents 1,000,000 times
$start_time = microtime(true);
$file = "small_file.html";
for($i=0;$i<1000000;$i  ){
    $set_time = file_get_contents($file);
}
$end_time = microtime(true);

$time_for_file_get_contents = ($end_time-$start_time);

echo "<p>Working on a file that is $file_size B long</p>
<p>filemtime: $time_for_filemtime vs file_get_contents: $time_for_file_get_contents";
  

Результаты

Работа над файлом длиной 41 Б

время файла: 0.36287999153137 против file_get_contents: 16.191468000412

Никаких потрясений: «запросить у файловой системы некоторые метаданные» быстрее, чем «открыть файл, прочитать его и сравнить содержимое».

Ответ №3:

Для статистики файла вы просто запрашиваете у файловой системы некоторые метаданные.

Ваш второй подход включает в себя открытие файла, его чтение и сравнение содержимого.

Как вы думаете, что было бы быстрее? 😉

Комментарии:

1. Это имеет смысл, но есть еще вопрос по этому поводу, например, оптимизирована ли файловая система для чтения файлов вместо метаданных. Добавьте к этому стоимость самой операции кэширования для получения статистики PHP.

2. Еще один фактор, который следует учитывать. Используя первый подход, мне в конечном итоге придется читать содержимое при обнаружении модификации путем сравнения времени модификации. Я помню что-то под названием FileSystemWatch где-то, но на самом деле не помню этого.

Ответ №4:

Я думаю, что лучший способ получать уведомления об изменениях в файле — это inotify , который предназначен именно для этой цели.

Смотрите расширение inotify.