is_file与file_exists在PHP中的性能,以及缓存的使用?

9

我进行了一些测试,比较和测量两个函数的速度。 is_file 似乎比 file_exists 快几倍(我对两个函数都使用了10000次迭代)。我想知道PHP或操作系统是否为这些函数使用了缓存,还是总是访问硬盘?我认为不是,但我想知道...

我使用了这段代码:

<?php
$time = microtime();
$time = explode(' ', $time);
$begintime = $time[1] + $time[0];
for($i=0;$i<10000;$i++)
    file_exists('/Applications/MAMP/htdocs/index.php');
$time = microtime();
$time = explode(" ", $time);
$endtime = $time[1] + $time[0];
$totaltime = ($endtime - $begintime);
echo 'PHP parsed this in ' .$totaltime. ' seconds.</br>';
$time = microtime();
$time = explode(" ", $time);
$begintime = $time[1] + $time[0];
for($i=0;$i<10000;$i++)
    is_file('/Applications/MAMP/htdocs/index.php');
$time = microtime();
$time = explode(" ", $time);
$endtime = $time[1] + $time[0];
$totaltime = ($endtime - $begintime);
echo 'PHP parsed this in ' .$totaltime. ' seconds.</br>';
?>

3
您是否在一个紧密循环中多次调用此操作(导致该效果占据请求时间的主导地位)?如果不是,除非您确定它会导致性能问题,否则不必担心它......请记住,“过早优化是万恶之源”......在确定确实存在问题后,使用语义更好的替代方案进行优化。 - ircmaxell
实际上,is_file() 比 file_exists() 快了整整10倍!我刚试过了,这是真的。 - forthrin
如果有帮助的话,我们可以补充说明file_exists()函数将会对存在的目录和文件都返回true,而is_file()函数只会在它是一个文件(当然也必须存在)时返回true。 - aesede
3个回答

13
当您使用stat()、lstat()或下面列出的其他受影响函数时,PHP会缓存这些函数返回的信息,以提供更快的性能。但在某些情况下,您可能想清除缓存的信息。例如,如果在单个脚本中多次检查同一文件,并且该文件在脚本运行期间有被删除或更改的风险,则可以选择清除状态缓存。在这种情况下,您可以使用clearstatcache()函数来清除PHP关于文件的缓存信息。
受影响的函数包括stat()、lstat()、file_exists()、is_writable()、is_readable()、is_executable()、is_file()、is_dir()、is_link()、filectime()、fileatime()、filemtime()、fileinode()、filegroup()、fileowner()、filesize()、filetype()和fileperms()。

2
但是这两个函数都在列表中,所以这似乎无法解释为什么一个比另一个快得多。 - thomasrutter
6
你首先执行file_exists()测试,它需要从磁盘读取并存储到statcache;然后你执行is_file(),它只是读取已由file_exists()检查所填充的statcache条目,因此速度会更快。在测试之间刷新缓存,这样你就可以准确地测试is_file(),因为它将不得不以与file_exists()相同的方式检查磁盘并填充缓存。 - Mark Baker
1
你的回复太慢了。请确保改进一下 ;) - thomasrutter

11

PHP会将is_file()file_exists()都缓存到stat缓存中。调用clearstatcache()来清除它。

编辑:
如果考虑任何因素,这两个函数执行时间应该相似,因为它们都会调用操作系统的stat()函数,但其中一个的结果可能会被PHP(除非你使用clearstatcache())或操作系统缓存,就像Yuliy在下面所述。


2
请注意,文件操作的性能测量可能会受操作系统文件系统缓存的影响而发生变化。 - Yuliy
strace shows file_exists calls access("foo", F_OK) while is_file does stat("foo", 0x7fffe720a8a0) - Bell

1

is_filefile_exists 是两个不同的函数,它们执行两种不同的操作;file_exists 只是检查文件是否存在,而 is_file 则判断目标是否为有效文件,例如不是一个目录。

它们不应该用于相同的目的,因此不能进行性能比较(在我看来)。


1
这并不完全正确。无论函数如何设计,目标都是实现所需的结果。在这种情况下,如果文件不存在,则is_file()和file_exists()都返回false。而基准测试证明,使用is_file()将使您的应用程序比使用file_exists()的类似应用程序更具优势。 - bcosca
@stillstanding:但我们在谈论什么样的优势呢?由于磁盘stat()将是最慢的部分,如果两者之间的差异不超过也许1或2%,我会感到惊讶。毕竟,两者都使用相同的数据,只是一个更快地返回(并且两者都应该只进行一次系统调用)...至少这是我的理解... - ircmaxell
确切地说,@R. Bemrose... 伪代码应该是 file_existsreturn false !== stat(),而对于 is_file$stat = stat(); if ($stat !== false) { return ($stat['mode_t'] & S_IFREG) != 0; } return false。因此,is_file 应该会更慢一些(但不会太多,因为 stat() 仍然会支配其他简单语言结构)。 - ircmaxell
我的系统进行了一个快速的基准测试(调用clearstatcache()显示它们在误差范围内(平均差约1%)......因此(至少在我的ext3文件系统上),实际上几乎没有什么区别(因为如预期所示,stat()系统调用占用时间)......并且记录file_exists()不检查它是文件还是目录,它只是检查文件系统对象是否存在(并且不关心类型,它可能是块设备,只要有这个名称的东西存在)。 - ircmaxell
@ircmaxell:这正是我所指的。 - Strae
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接