百度工程师讲PHP函数的实现原理及性能分析(二)


Posted in PHP onMay 13, 2015

类方法
类方法其执行原理和用户函数是相同的,也是翻译成opcodes顺次调用。类的实现,zend用一个数据结构zend_class_entry来实现,里面保存了类相关的一些基本信息。这个entry是在php编译的时候就已经处理完成。
在 zend_function的common中,有一个成员叫做scope,其指向的就是当前方法对应类的zend_class_entry。关于php中面向对象的实现,这里就不在做更详细的介绍,今后将专门写一篇文章来详述php中面向对象的实现原理。就函数这一块来说,method实现原理和 function完全相同,理论上其性能也差不多,后面我们将做详细的性能对比。

性能对比
函数名长度对性能的影响

》》测试方法 对名字长度为1、2、4、8、16的函数进行比较,测试比较它们每秒可执行次数,确定函数名长度对性能的影 响

》》测试结果如下图
百度工程师讲PHP函数的实现原理及性能分析(二)

》》结果分析
从图上可以看出,函数名的长度对性能还是会有一定的影响。一个长度为1的函数和长度为16的 空函数调用 ,其性能差了1倍。分析一下源码不难找到原因,如前面叙述所说,函数调用的时候zend会先在一个全局的funtion_table中通过函数名查询相关信息,function_table是一个哈希表。必然的,名字越长查询所需要的时间就越多。 因此,在实际编写程序的时候,对多次调用的函数,名字建议不要太长。

虽然函数名长度对性能有一定影响,但具体有多大呢?这个问题应该还是需要结合实际情况来考虑,如果一个函数本身比较复杂的话,那么对整体的性能影响并不大。一个建议是对于那些会调用很多次,本身功能又比较简单的函数,可以适当取一些言简意赅的名字。
函数个数对性能的影响

》》测试方法
在以下三种环境下进行函数调用测试,分析结果:1.程序仅包含1个函数 2.程序包含100个函数 3.程序包含1000个函数。测试这三种情况下每秒所能调用的函数次数

》》测试结果如下图
百度工程师讲PHP函数的实现原理及性能分析(二)

》》结果分析
从测试结果可以看出,这三种情况下性能几乎相同,函数个数增加时性能下降微乎其微,可以忽略。从实现原理分析,几种实现下唯一的区别在于函数获取的部分。如前文所述,所有的函数都放在一个hash表中,在不同个数下查找效率都应该还是接近于O(1),所以性能差距不大。
不同类型函数调用消耗
》》测试方法
选取用户函数、类方法、静态方法、内置函数各一种,函数本身不做任何事情,直接返回,主要测试空函数调用的消耗。测试结果为每秒可执行次数 测试中为去除其他影响,所有函数名字长度相同
》》测试结果如下图

》》结果分析
通过测试结果可以看到,对于用户自己编写的php函数,不管是哪种类型,其效率是差不多的,均在280w/s左右。如我们预期,即使是空调,内置函数其效率也要高很多,达到780w/s,是前者是3倍。可见,内置函数调用的开销还是远低于用户函数。从前面原理分析可知主要差距在于用户函数调用时初始化符号表、接收参数等操作。

内置函数和用户函数性能对比

》》测试方法
内置函数和用户函数的性能对比,这里我们选取几个常用的函数,然后用php实现相同功能的函数进行一下性能对比。测试中,我们选取字符串、数学、数组中各一个典型进行对比,这几个函数分别是字符串截取(substr)、10进制转2进制(decbin)、求最小值(min)和返回数组中的所以 key(array_keys)。
》》测试结果如下图
百度工程师讲PHP函数的实现原理及性能分析(二)
》》结果分析
从测试结果可以看出,如我们预期,内置函数在总体性能上远高于普通用户函数。尤其对于涉及到字符串类操作的函数,差距达到了1个数量级。因此,函数使用的一个原则就是如果某功能有相应的内置函数,尽量使用它而不是自己编写php函数。对于一些涉及到大量字符串操作的功能,为提高性能,可以考虑用扩展来实现。比如常见的富文本过滤等。
和C函数性能对比

》》测试方法
我们选取字符串操作和算术运算各3种函数进行比对,php用扩展实现。三种函数是简单的一次算法运算、字符串比较和多次的算法运算。除了本身的两类函数外,还会测试将函数空调开销去掉后的性能,一方面比对一下两种函数(c和php内置)本身的性能差异,另外就是侧面印证空调函数的消耗 测试点为执行10w次操作的时间消耗
》》测试结果如下图
百度工程师讲PHP函数的实现原理及性能分析(二)

》》结果分析
内置函数和C函数的开销在去掉php函数空调用的影响后差距较小,随着函数功能越来越复杂,双方性能趋近于相同。这个从之前的函数实现分析中也容易得到论证,毕竟内置函数就是C实现的。函数功能越复杂,c和php的性能差距越小 相对c来说,php函数调用的开销大很多,对于简单函数来说性能还是有一定影响。因此php中函数不宜嵌套封装太深。
伪函数及其性能

在php中,有这样一些函数,它们在使用上是标准的函数用法,但底层实现却和真正函数调用完全不同,这些函数不属于前文提到的三种function中的任何一类,其实质是一条单独的opcode,这里估且叫做伪函数或者指令函数。

如上所说,伪函数使用起来和标准的函数并无二致,看起来具有相同的特征。但是他们最终执行的时候是被zend反映成了一条对应的指令(opcode)来调用,因此其实现更接近于if、 for、算术运算等操作。
》》php中的伪函数
isset
empty
unset
eval
通过上面的介绍可以看出,伪函数由于被直接翻译成指令来执行,和普通函数相比少了一次函数调用所带来的开销,因此性能会更好一些。我们通过如下测试来做一个对比。 Array_key_exists和isset两者都可以判断数组中某个key是否存在,看一下他们的性能
百度工程师讲PHP函数的实现原理及性能分析(二)
从图上可以看出,和 array_key_exists相比,isset性能要高出很多,基本是前者的4倍左右,而即使是和空函数调用相比,其性能也要高出1倍左右。由此也侧面印证再次说明了php函数调用的开销还是比较大的。

PHP 相关文章推荐
PHP 实例化类的一点摘记
Mar 23 PHP
选择PHP作为网站开发语言的原因分享
Jan 03 PHP
ThinkPHP实现事务回滚示例代码
Jun 23 PHP
ThinkPHP分页实例
Oct 15 PHP
PHP连接MSSQL时nvarchar字段长度被截断为255的解决方法
Dec 25 PHP
WordPress开发中用于标题显示的相关函数使用解析
Jan 07 PHP
PHP爬虫之百万级别知乎用户数据爬取与分析
Jan 22 PHP
php array_multisort 对数组进行排序详解及实例代码
Oct 27 PHP
php 使用redis锁限制并发访问类示例
Nov 02 PHP
PHP+iframe图片上传实现即时刷新效果
Nov 18 PHP
PHP输出多个元素的排列或组合的方法
Mar 14 PHP
PHP date_default_timezone_set()设置时区操作实例分析
May 16 PHP
百度工程师讲PHP函数的实现原理及性能分析(一)
May 13 #PHP
PHP版本如何选择?应该使用哪个版本?
May 13 #PHP
PHP Hash算法:Times33算法代码实例
May 13 #PHP
你应该知道PHP浮点数知识
May 13 #PHP
PHP浮点数精度问题汇总
May 13 #PHP
PHP生成器简单实例
May 13 #PHP
php实现比较两个字符串日期大小的方法
May 12 #PHP
You might like
php引用返回与取消引用的详解
2013/06/08 PHP
PHP+JQuery+Ajax实现分页方法详解
2016/08/06 PHP
PHP用swoole+websocket和redis实现web一对一聊天
2019/11/05 PHP
Avengerls vs Newbee BO3 第一场2.18
2021/03/10 DOTA
CSDN轮换广告图片轮换效果
2007/03/27 Javascript
css transform 3D幻灯片特效实现步骤解读
2013/03/27 Javascript
PHP+jQuery+Ajax实现多图片上传效果
2015/03/14 Javascript
JS动态创建元素的两种方法
2016/04/20 Javascript
js中遍历Map对象的方法
2016/07/27 Javascript
微信小程序 前端源码逻辑和工作流详解
2016/10/08 Javascript
JavaScript箭头(arrow)函数详解
2017/06/04 Javascript
vue富文本框(插入文本、图片、视频)的使用及问题小结
2018/08/17 Javascript
Mint-UI时间组件起始时间问题及时间插件使用
2018/08/20 Javascript
通过vue写一个瀑布流插件代码实例
2019/09/07 Javascript
electron 如何将任意资源打包的方法步骤
2020/04/16 Javascript
利用React高阶组件实现一个面包屑导航的示例
2020/08/23 Javascript
Vue 集成 PDF.js 实现 PDF 预览和添加水印的步骤
2021/01/22 Vue.js
[05:49]DOTA2-DPC中国联赛 正赛 Elephant vs LBZS 选手采访
2021/03/11 DOTA
pip 错误unused-command-line-argument-hard-error-in-future解决办法
2014/06/01 Python
PyCharm使用教程之搭建Python开发环境
2016/06/07 Python
Python操作使用MySQL数据库的实例代码
2017/05/25 Python
Python3 操作符重载方法示例
2017/11/23 Python
Python简单获取网卡名称及其IP地址的方法【基于psutil模块】
2018/05/24 Python
python pandas库中DataFrame对行和列的操作实例讲解
2018/06/09 Python
Python控制键盘鼠标pynput的详细用法
2019/01/28 Python
python使用PyQt5的简单方法
2019/02/27 Python
Python3.4学习笔记之列表、数组操作示例
2019/03/01 Python
戴尔美国官方折扣店:Dell Outlet
2018/02/13 全球购物
如何设定的weblogic的热启动模式(开发模式)与产品发布模式
2012/09/08 面试题
软件设计的目标是什么
2016/12/04 面试题
个人考核材料
2014/05/15 职场文书
党员干部反四风民主生活会对照检查材料思想汇报
2014/10/12 职场文书
志愿者事迹材料
2014/12/26 职场文书
个人先进事迹材料
2014/12/29 职场文书
学校中秋节活动总结
2015/03/23 职场文书
Python 线程池模块之多线程操作代码
2021/05/20 Python