php中include_once和require_once性能分析

文章来给各位朋友介绍PHP中include_once和require_once性能分析,有需要了解的朋友不防参考参考.

我们知道,PHP去判断一个文件是否被加载,是需要得到这个文件的opened_path的.

实例代码如下:

  1.    set_include_path(/tmp/:/tmp2/); 
  2.    include_once(2.PHP); 
  3.    ?> 

PHP看到include_once “2.PHP”的时候,他并不知道这个文件的实际路径是什么,也就无法从已加载的文件列表去判断是否已经加载,所以在include_once的实现中,会首先尝试解析这个文件的真实路径(对于普通文件这个解析仅仅类似是检查getcwd和文件路径,所以如果是相对路径,一般是不会成功),如果解析成功,则查找EG(include_files),如果存在则说明包含过了,返回,否则open这个文件,从而得到这个文件的opened_path. 比如上面的例子,这个文件存在于 “/tmp2/2.PHP”.

然后,得到了这个opened_path以后,PHP去已加载的文件列表去查找,是否已经包含,如果没有包含,那么就直接compile,不再需要open file了.

1. 尝试解析文件绝对路径,如果能解析成功,则检查EG(included_files),存在则返回,不存在继续

2. 打开文件,得到文件的打开路径(opened path)

3. 拿opened path去EG(included_files)查找,是否存在,如果存在则返回,不存在继续

4. 编译文件(compile_file)这个在大多数情况下,不是问题,然而问题出在当你使用APC的时候…

在使用APC的时候,APC劫持了compile_file这个编译文件的指针,从而直接从cache中得到编译结果,避免了对实际文件的open,避免了对open的system call.然而,当你在代码中使用include_once的时候,在compile_file之前,PHP已经尝试去open file了,然后才进入被APC劫持的compile file中,这样一来,就会产生一次额外的open操作. 而APC正是为了解决这个问题,引入了include_once_override,在include_once_override开启的情况下,APC会劫持PHP的ZEND_INCLUDE_OR_EVAL opcode handler,通过stat来确定文件绝对路径,然后如果发现没有被加载,就改写opcode为include,做一个tricky解决方案.但是,很可惜,如我所说,APC的include_once_override实现的一直不好,会有一些未定义的问题.

实例代码如下:

  1.     set_include_path(/tmp); 
  2.     function a($arg = array()) { 
  3.         include_once(b.PHP); 
  4.     } 
  5.     a(); 
  6.     a(); 
  7.     ?> 

然后,我们的b.PHP放置在”/tmp/b.PHP”,内容如下:

实例代码如下

  1.       class B {} 
  2.     ?> 

那么在打开apc.include_once_override的情况下,连续访问就会得到如下错误:

Fatal error – include() : Cannot redeclare class

排除这些技术因素,我也一直认为,我们应该使用include,而不是include_once,因为我们完全能做到自己规划,一个文件只被加载一次. 还可以借助自动加载,来做到这一点.你使用include_once,只能证明,你对自己的代码没信心.所以,建议大家,不要再使用include_once,不过我建义大家使用autoload和spl_autoload自动加载

(1) autoload机制概述

在使用PHP的OO模式开发系统时,通常大家习惯上将每个类的实现都存放在一个单独的文件里,这样会很容易实现对类进行复用,同时将来维护时也很便利.这 也是OO设计的基本思想之一.在PHP5之前,如果需要使用一个类,只需要直接使用include/require将其包含进来即可.下面是一个实际的例子:

实例代码如下

  1. /* Person.class.PHP */ 
  2. class Person { 
  3. var $name$age
  4. function __construct ($name$age
  5. $this->name = $name
  6. $this->age = $age
  7. ?> 
  8. /* no_autoload.PHP */ 
  9. require_once (”Person.class.PHP”); 
  10. $person = new Person(”altair”, 6); 
  11. var_dump ($person); 
  12. ?> 

在这个例子中,no-autoload.PHP文件需要使用Person类,它使用了require_once将其包含,然后就可以直接使用Person类来实例化一个对象.但随着项目规模的不断扩大,使用这种方式会带来一些隐含的问题:如果一个PHP文件需要使用很多其它类,那么就需要很多的require/include语 句,这样有可能会造成遗漏或者包含进不必要的类文件.如果大量的文件都需要使用其它的类,那么要保证每个文件都包含正确的类文件肯定是一个噩梦.

PHP5为这个问题提供了一个解决方案,这就是类的自动装载(autoload)机制.autoload机制可以使得PHP程序有可能在使用类时才自动包含类文件,而不是一开始就将所有的类文件include进来,这种机制也称为lazy loading.下面是使用autoload机制加载Person类的例子:

实例代码如下:

  1. /* autoload.PHP */ 
  2. function __autoload($classname) { 
  3. require_once ($classname . “class.PHP”); 
  4. $person = new Person(”altair”, 6); 
  5. var_dump ($person); 
  6. ?> 

相关文章

统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
前言 之前做了微信登录,所以总结一下微信授权登录并获取用户...
FastAdmin是我第一个接触的后台管理系统框架。FastAdmin是一...
之前公司需要一个内部的通讯软件,就叫我做一个。通讯软件嘛...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...