PHP 是不是包含资源昂贵(特别是在迭代期间)?
Posted
技术标签:
【中文标题】PHP 是不是包含资源昂贵(特别是在迭代期间)?【英文标题】:Is PHP's include resource-expensive (particularly during iterations)?PHP 是否包含资源昂贵(特别是在迭代期间)? 【发布时间】:2011-09-21 10:00:54 【问题描述】:php 是否缓存 include
请求?我想知道如何清理我的代码,并考虑使用更多includes
。考虑以下方案。
[foreach answer] [include answer.tpl.php] [/foreach]
这需要包含answer.tpl.php
数百次。
它会缓存吗?它会对性能产生值得考虑的影响吗? 这被认为是一种好习惯吗?不好?
回应@Aaron Murray 的回答
不,这行不通。 _once
的唯一概念是防止多次包含同一个文件。 (防止因覆盖常量值等引起的错误)
实际示例如下所示:
# index.php
<?php
$array = array('a', 'b', 'c');
$output = '';
foreach($array as $e)
$output .= require_once 'test.php';
echo $output;
# test.php
<?php
return $e;
【问题讨论】:
文件的内容将被 OS 文件缓存缓存,但仍然会有开销执行 stat() 调用等以查看自上次加载以来文件是否已更改。 更不用说必须解析文件的内容并评估其中的所有 PHP 代码(如果有的话)。require_once
没有返回值。这不是一个函数。
操作系统很好地缓存了隐含的文件请求。 PHP 本身没有。但这通常是无关紧要的,因为现在字节码缓存 (APC) 非常普遍。
@mario:我确实使用 APC。那么,如果 APC 正在使用中,这有点意味着 include
也被缓存了?
【参考方案1】:
PHP 是否缓存
include
请求?
据我所知,PHP 默认不缓存包含。但是您的底层文件系统可能会这样做。因此,在您的示例中一遍又一遍地访问同一个文件应该很快。
如果您遇到实际问题,您首先需要分析应用程序以找出实际瓶颈所在。因此,除非您还没有遇到任何问题,否则我会考虑使用无害的包含。
关于良好实践,我认为这篇文章对此进行了很好的解释:When Flat PHP meets Symfony。
让您的代码更具可重用性
这并不是什么高大上的设计,只是为了展示如何开始让事情变得更加模块化。您应该能够从包含文件中获取 1:1 的代码,只需注意将所有需要的模板变量传递到函数中(不要为此使用全局变量,它迟早会妨碍您):
# in your answer.tpl.php
function answer_template(array $vars)
extract($vars);
... your template code ...
# your script
array = array('a', 'b', 'c');
$output = '';
require('answer.tpl.php');
foreach($array as $e)
$output .= answer_template(compact('e'));
echo $output;
【讨论】:
感谢您的回答。不过,-1 表示 Symfony 和afaik
的参考链接。以糟糕的方式编写代码并仅在代码损坏(或您开始遇到资源问题)时进行修复通常是一个糟糕的建议。
@Guy:链接的文章展示了一张一般的图片。它并没有隐瞒它来自 symfony,但不管任何类型的框架,它都是一本好书。不要仅仅因为标题而判断。第二点是,过早的优化往往是问题的根源,而不是解决方案。在查看您的代码时,我会首先考虑一些设计改进,然后再推测磁盘 I/O。因此,这不是一个忽略问题的建议,而是专门针对正确定位问题的建议。【参考方案2】:
您是否考虑过:
require_once('answer.tpl.php')
or
include_once('answer.tpl.php')
当然,您可以仅在您希望它们包含的脚本中包含“必需”文件(仅在真正需要它们的地方)。
编辑:修改答案:
index.php ->
require_once('answer.php');
echo answer(); // This function can be called from anywhere in the scripts.
answer.php ->
function answer()
return '<div>This is the answer</div>';
另外,您可以在函数中使用输出缓冲来在 answer.php 中捕获 html(用于分离 HTML 和 php 的更简洁的方法)。
回应你上面的例子:
index.php
<?php
require_once('test.php');
$array = array('a', 'b', 'c');
$output = '';
foreach($array as $e)
$output .= test($e);
echo $output;
test.php
<?php
function test($param)
return $param;
【讨论】:
如果只包含一次,其余迭代会发生什么?_once
的概念是不允许多次包含相同的代码。 The require_once() statement is identical to require() except PHP will check if the file has already been included, and if so, not include (require) it again.
来自php.net
在模板的情况下,您可以将输出包装在一个函数或类中,然后 require_once 文件,然后从多个位置调用它。例如 answer.tpl.php -> function answer() echo '<div>This is my output</div>';
并在需要它的脚本中:echo answer()
当然,您也可以将参数传递添加到您创建的函数/类。
因此,您可以在调用脚本的顶部需要它一次,并在整个执行过程中使用该函数或类。【参考方案3】:
这个话题之前出现过,所以这里有一些潜在的重复(不认可任何;大部分是部分答案,但相关阅读):
What's the performance cost of "include" in PHP? Is it bad to include a lot of files in PHP like it is for file based Sessions? Will reducing number of includes/requires increase performance? Why is require_once so bad to use? Which is better performance in PHP?嗯,这些都没有专门回答你的问题。我们在某处有一点性能基准,但我找不到。
(我个人经常组织我的代码以将整个应用程序合并到一个 blob 文件中,然后去除空格,以避免多个文件访问,即使 APC 存在。)
【讨论】:
以上是关于PHP 是不是包含资源昂贵(特别是在迭代期间)?的主要内容,如果未能解决你的问题,请参考以下文章
有人可以推荐一个关于 MySQL 索引的好教程,特别是在连接期间在 order by 子句中使用时? [关闭]
Java中的集合(十五) Iterator 和 ListIteratorEnumeration