【问题标题】:Cost of file modification time checks文件修改时间检查成本
【发布时间】:2011-08-16 13:12:06
【问题描述】:

对于Linux下包含几个字节的文件,我只需要处理它自上次处理以来的更改时间。 我通过定期调用 PHP clearstatcache(); filemtime(); 检查文件是否被更改。 由于整个文件总是很小,删除对 filemtime 的调用并通过将内容与过去的内容进行比较来检查文件更改是否会提高性能? 或者,就性能而言,最好的方法是什么。

【问题讨论】:

  • 我认为非常非常困难。 filemtime() 访问低级系统功能,这些功能总是会在实际打开它时胜过。有兴趣听听文件系统/操作系统专家怎么说
  • 可能取决于操作系统和文件系统类型。分析两者,看看哪一个在您的特定设置中效果更好。
  • @Mat - 我想不出一个比元数据更快地返回文件内容的文件系统......如果有的话,我想我不想使用它。
  • @Brian:如果经常访问文件,数据和元数据都将被缓存 - 仅将元数据复制到用户空间与复制文件数据的几个字节之间的时间差可能很难在现代系统上进行测量。如果它真的很小,那么比较可能与与时间戳相比一样便宜 - 如果时间戳在 32 位系统上为 64 位长,甚至可能更便宜。 (但系统调用开销可能占主导地位,所以...)
  • @Mat - 哦,我同意,考虑到无法衡量的差异,这个问题本身就是愚蠢的。但是,如果文件发生更改,则需要更新缓存。而且我敢打赌,驱动器上的寻道时间会抵消任何处理 64 位数字的问题。这个对话现在使用的时间比这里的任何“优化”多年来节省的时间都多:-D

标签: php performance filemtime


【解决方案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 */

【讨论】:

  • 请注意,如果您在同一请求期间需要多次从同一文件中获取新的filemtime信息,您只需致电clearstatcache();(如果有可能鉴于文件可能在请求期间被修改)。 filemtime 缓存在请求完成后丢失。
【解决方案2】:

我知道我参加聚会迟到了,但一点点基准测试永远不会影响讨论。即使在您考虑比较步骤之前,Brian Roach 的直觉也能证明声音:

测试:

$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 B 长的文件

filemtime:0.36287999153137 vs file_get_contents:16.191468000412

毫无疑问:“向文件系统询问一些元数据”比“打开文件、读入并比较内容”要快。

【讨论】:

    【解决方案3】:

    要统计文件,您只需向文件系统询问一些元数据。

    您的第二种方法是打开文件、读入文件并比较内容。

    你认为哪个会更快? ;)

    【讨论】:

    • 这是有道理的,但在这方面还有更多问题要问,比如文件系统是否针对文件读取而不是元数据进行了优化。再加上 PHP 统计的缓存操作本身的成本。
    • 另一个需要考虑的因素。使用第一种方法,当通过比较修改时间检测到修改时,我最终将不得不读取内容。我记得某处有一个叫做 FileSystemWatch 的东西,但不记得了。
    【解决方案4】:

    我认为通知文件更改的最佳方法是inotify,它正是为此目的而设计的。

    请参阅inotify extension

    【讨论】:

      猜你喜欢
      • 2017-03-23
      • 2013-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 2012-03-13
      相关资源
      最近更新 更多