为什么使用require_once是不好的?

16 浏览
0 Comments

为什么使用require_once是不好的?

关于更好的PHP编码实践的所有阅读材料都说不要使用require_once,因为它会影响速度。\n为什么会这样?\n如何以更适当/更好的方式执行与require_once相同的操作?如果有关PHP 5的问题,那又该怎么做呢?

0
0 Comments

为什么使用require_once很糟糕?

在这篇文章中,作者通过实验证明了使用require而不是require_once的原因。作者创建了100个使用require_once来包含其他头文件的头文件。作者使用了PHP 5.2.0进行比较。作者又创建了一个app.php来加载这100个文件。作者对比了使用require_once和require来包含头文件时的差异。作者在运行100次的测试中没有发现太大的差异。作者又重复了使用10000个输入文件的实验,这次发现了一致的差异。作者使用strace来分析所做的系统调用。作者发现使用require_once比使用require多了一些系统调用。作者得出的结论是,使用绝对路径而不是相对路径可以减少系统调用的数量。

这篇文章的结论是,使用require或require_once都没有太大的差异,使用哪个取决于个人喜好。

0
0 Comments

为什么使用require_once会有问题?

require_onceinclude_once都要求系统记录已经被包含/引入的文件。每次*_once调用都需要检查记录。所以肯定会有一些额外的工作,但是会影响整个应用程序的速度吗?...我真的怀疑...除非你使用非常旧的硬件或者非常频繁地使用它。

如果你确实使用了成千上万次的*_once,你可以以一种更轻量的方式自己完成这项工作。对于简单的应用程序,只需确保只包含一次*_once应该就足够了,但是如果仍然出现重定义错误,你可以像这样做:

if (!defined('MyIncludeName')) {
    require('MyIncludeName');
    define('MyIncludeName', 1);
}

个人上我会继续使用*_once语句,但是在一个愚蠢的百万次基准测试中,你可以看到两者之间的差异:

                php                  hhvm
if defined      0.18587779998779     0.046600103378296
require_once    1.2219581604004      3.2908599376678

require_once慢了10-100倍,而且有趣的是hhvm中的require_once似乎更慢。再次强调,只有当你运行成千上万次的*_once时,这才与你的代码相关。


<?php // test.php
$LIMIT = 1000000;
$start = microtime(true);
for ($i=0; $i<$LIMIT; $i++)
    if (!defined('include.php')) {
        require('include.php');
        define('include.php', 1);
    }
$mid = microtime(true);
for ($i=0; $i<$LIMIT; $i++)
    require_once('include.php');
$end = microtime(true);
printf("if defined\t%s\nrequire_once\t%s\n", $mid-$start, $end-$mid);


<?php // include.php
// do nothing.

我怀疑你的defined()方法比内置的查找表更快,但是我同意你的总体观点-这确实是个非问题!

我非常确定你是对的Bobby,但我并不主张使用defines来替代_once。这只是一个选择。解释代码所需的时间甚至可能使其稍微慢一些,但是话虽如此,我不知道内部方法的彻底程度。它可能会做一些额外的工作以确保没有重复。

另一个缺点是APC不会缓存include_once和require_once调用,我IRC刚刚对这两种方法进行了一个非常基本的测试-我进行了1000000次迭代,包含了一个简单地将常量'testinclude'定义为true的文件。在第一次测试中,我使用了require_once,第二次我使用了if(!defined('testinclude')),结果很有趣:Require: 0.81639003753662 Not Defined: 0.17906713485718 Defined比Not Defined快了0.63732290267944微秒。

使用define的情况会更快,因为你不需要执行任何额外的检查,比如使用realpath。这不是在比较两个完全相同的东西。

0
0 Comments

为什么使用require_once很糟糕?

这个问题的出现原因是因为在PHP中,使用require_once的性能是很差的。定义常量非常耗费资源,如果使用require_once来包含类文件,其实是没有必要定义常量的。可以通过class_exists('Classname')来检查类是否存在。

在过去的一段时间里,很多人使用class_exists()方法来进行包含,因为require_once在较早的PHP版本中性能较差。但是现在这个问题已经修复了,额外的字节码编译和方法调用所带来的开销已经远远超过了内部哈希表的检查。

在PHP中,包含文件是昂贵的,因为每次解释器遇到一个包含文件时,都需要切换到解析模式,生成操作码,然后再跳回来。如果有100个以上的包含文件,肯定会影响性能。使用require_once会给opcode缓存带来困扰。

如果在解析时,你知道整个请求的生命周期中会需要哪些包含文件,就在开始时使用require()进行包含,opcode缓存会处理剩下的事情。

如果不使用opcode缓存,就比较难处理了。将所有的包含文件内联到一个文件中(只在生产环境中使用,不要在开发中使用)可以提高解析时间,但是这样做很麻烦,而且你需要准确知道在请求期间会包含哪些文件。

自动加载很方便,但是慢,因为每次包含都需要运行自动加载逻辑。实际上,我发现为一个请求自动加载几个特定的文件不会造成太大的问题,但是你不应该自动加载所有需要的文件。

如果只有大约10个包含文件,这种优化是不值得的:只需优化数据库查询或其他操作。

虽然这个结论已经过时,但是define(),require_once()和defined()在我的机器上每个都需要大约1-2微秒。

尽管只是2微秒,但这比用户等待页面加载的时间要长。一年的页面浏览时间内,这可以为用户节省整整3秒!他们可以在这个时间里看十分之一的广告!考虑用户,不要浪费微秒。

class_exists('Classname')检查类名是否已经包含,而require_once()检查文件是否已经包含。需要注意的是,多个文件可能包含相同的类。

你对于所有的讽刺都是错误的。你对PHP也不了解,它也可以运行在微处理器上,你PC上的1微秒在微处理器上可能是几毫秒。那么如果有20个包含文件,一个较大的项目呢?就会引入20倍的几毫秒延迟,这对人类来说是可以察觉的。如果这个脚本经常被调用,将会对系统性能产生影响。优化不是一个玩笑,整个世界并不围绕你的电脑转。有成千上万的CPU正在使用。

这只是一个开玩笑,没有恶意。如果你认为优化你的包含文件是值得的,就去做吧。

只是试图表明PHP的世界不仅仅局限于Ghz的电脑。如果在30Mhz的CPU上运行它,所有的性能问题都会累积起来。

30Mhz?O_O 5年前发布的最慢的Raspberry Pi是700Mhz。如果有人在30Mhz的CPU上运行PHP,他们可能选择了错误的工具。

树莓派是标准吗?:)但是即使在700MHZ的ARM上(请注意,这与700MHz的Intel Core性能相去甚远),它也会有所影响。尤其是如果有很多包含文件和很多调用。这都会累积起来。我个人在比当前树莓派慢得多的嵌入式电脑上使用了PHP,而且这种类型的电脑在市场上仍然有成千上万的使用。PHP并不是一个糟糕的选择。

0