File_exists vs suppress include,这是PHP中更快的失败方式

时间:2012-12-04 14:30:14

标签: php optimization file-io

TL; DR

执行file_exists或检查@include的返回值(即抑制错误)是否更快?

在这种情况下,您可以假设我使用的是绝对路径,而不是依赖include_path解析。

精心制作的版本

使用框架和/或软件在其引导过程中具有的所有条件代码,我开始怀疑最快的失败方式,而不牺牲优雅。我有一个特定的用例,我想到了这个想法,即包括一个不一定存在的配置文件。

无论如何,这两个操作都会执行某个属性,因此无法避免磁盘访问。后一个选项具有额外的好处,即在成功时读取和解析文件,所以在我看来,这已经是一个非常大的奖励。

这实际上是一种极端的微优化,特别是在我的情况下,它只有一个文件,但问题仍然让我感到不安,我不知道如何正确地测试这个。

接受后的暴力测试

在得到正确的答案之后,我做了一些暴力测试。之前我不想这样做,因为我想从现场获得明智的答案。另外,我不想仅仅基于我的强力测试,因为我完全不确定这是测试它的正确方法。 (实际上,我很确定它不是。)

我所做的是运行以下代码片段:

<?php
$rounds = 1e6;
$start = microtime(true);

while ($rounds--) {
    @include "i-dont-exist";
    clearstatcache();
}

echo microtime(true) - $start, PHP_EOL;

...和...

<?php
$rounds = 1e6;
$start = microtime(true);

while ($rounds--) {
    file_exists("i-dont-exist");
    clearstatcache();
}

echo microtime(true) - $start, PHP_EOL;

...和...

<?php
$rounds = 1e6;
$start = microtime(true);

while ($rounds--) {
    @include "i-exist";
    clearstatcache();
}

echo microtime(true) - $start, PHP_EOL;

...和...

<?php
$rounds = 1e6;
$start = microtime(true);

while ($rounds--) {
    if (file_exists("i-exist")) @include "i-exist";
    clearstatcache();
}

echo microtime(true) - $start, PHP_EOL;

结果是:

不存在的文件

@include:27.090675830841
file_exists:1.0596489906311

现有文件

@include:19.758506059647
file_exists + include:22.083800077438

我们可以从中得出什么结论?好吧,至少,根据the answer by @goldencrater中提供的链接,抑制错误是很昂贵的。

一般来说,我认为压制错误也是愚蠢的 - 除非它是一个明智的选择,我认为我的用例验证的标准。

如果你包括一个包含文件失败后你将失败,在我看来,从包含的错误中抑制错误是合理的,因为失败的成本仅在失败的请求中推断。 (即,不会抑制和忽略错误。)对失败的请求投入大量成本远比在每个请求上花费很少的成本更糟糕。

1 个答案:

答案 0 :(得分:2)

尽管错误抑制(@)本身有很大的开销,但消除file_exists调用总是更快。

Smarty模板引擎背后的人改变了他们的整个代码库,使用@而不是file_exists(和类似的)检查,最终提高了速度。以下是其中一位作者详细介绍了这一变化的博文:http://blog.rodneyrehm.de/archives/12-Improving-Disk-IO-in-PHP-Apps.html