阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

PHP加载大文件时require和file_get_contents的性能对比

187次阅读
没有评论

共计 1885 个字符,预计需要花费 5 分钟才能阅读完成。

在开发过程中发现,用 require 来加载一个很大(几百 K,甚至几兆)的配置文件时,会造成响应超时。如果把这个配置文件的内容序列化后,用 file_get_contents 获取文件然后反序列化的方法来加载,就会快很多。

经过近两周的研究,大概知道了其中的原因。

首先,还从 PHP 的流程说起,PHP 其实有两个流程,一个是启动的流程,一个是响应请求的流程。PHP 作为 Apache 的一个模块,向 Apache 注册了两个函数,一个是 Aapche 启动的时候运行的函数:sapi_startup;一个是 Apache 接收到请求的时候调用的函数:php_handler

启动的流程:

Apache 启动

    ->  sapi_startup

        -> php_module_startup (PHP 启动总开关)

            -> zend_startup (启动 Zend 引擎,包括初始化全局变量,初始化 compile 和 execute 函数

 

相应请求的流程:

Apache 收到请求

    ->  sapi_startup

        -> zend_activate (包括初始化编译器、初始化执行器、启动扫描器)

            -> zend_compiler (语法分析、语意分析、生成 opcode)

                -> zend_execute (执行每个 opcode)

                    -> zend_deactive(清理本次请求用到的数据)

如果遇到 require 或者 include 之类的函数时,会 从 zend_execute 阶段重新回到 zend_compiler 阶段,开始解释 PHP,执行 PHP 的过程。

除了 zend_compiler 和 zend_execute 阶段之外,require 和 file_get_contents 的开销基本是一样的。

而且我们服务器上安装了 apc 扩展,就是说 zend_compiler 阶段可以认为两者也是一样的。

那他们的性能九差在 zend_execute 阶段了。

首先,让我们用 vld 扩展查看一下两个文件生成的 opcode 的数量,因为这个是 execute 的输入。

结果显示,require 生成的 opcode 数量为 2 万多个,大多是 ADD_ARRAY_ELEMENT,就是构造数据;而 file_get_contents 生成的 opcode 只有 6 个;

然后再来对比执行的效率:

这两个函数的执行可以分成两部分:读取文件和构造配置文件里面的数组;

先说读取文件,require 读取的机制是,以 8192 字节大小的 buffer 循环将文件读入内存;而 file_get_contents 使用的是 mmap,直接将文件映射到了虚拟内存当中。这样的话,require 会比 file_get_contents 多出大量的系统调用。而 file_get_contents 无需作这么多用户态和内核态的切换工作。这一步,file_get_contents 胜出一筹;

再来看构造数组,require 构造的机制是生成 2 万多个 opcode,然后一次执行这些 opcode;而 file_get_contents 使用的是 unserialize 函数,他对传入的文本进行解析,然后逐级构造成数组。他们构造数组的思路是一样的,但是 require 每增加一级数据的开销要比 unserialize 大;这一局也是 file_get_contents 略优;

但是,file_get_contents 在 PHP 内部是函数调用,而 require 是一个内置的 opcode,所以调用 file_get_contents 时的开销要比 require 略大;

所以,小文件的时候,file_get_contents 读取文件时 内存映射的优势发挥不出来,两者部分伯仲;大文件的时候,由于 require 要 2K2K 的循环调用 read 系统调用,就降低了他的性能。

CentOS 6.3 安装 LNMP (PHP 5.4,MyySQL5.6) http://www.linuxidc.com/Linux/2013-04/82069.htm

在部署 LNMP 的时候遇到 Nginx 启动失败的 2 个问题 http://www.linuxidc.com/Linux/2013-03/81120.htm

Ubuntu 安装 Nginx php5-fpm MySQL(LNMP 环境搭建) http://www.linuxidc.com/Linux/2012-10/72458.htm

《细说 PHP》高清扫描 PDF+ 光盘源码 + 全套教学视频 http://www.linuxidc.com/Linux/2014-03/97536.htm

PHP 的详细介绍 :请点这里
PHP 的下载地址 :请点这里

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-20发表,共计1885字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中