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

   这篇文章主要介绍了百度工程师讲PHP函数的实现原理及性能分析(三),本文讲解了常用php函数实现及介绍,并作了总结及建议,需要的朋友可以参考下

  常用php函数实现及介绍

  count

  count是我们经常用到的一个函数,其功能是返回一个数组的长度。

  count这个函数,其复杂度是多少呢? 一种常见的说法是count函数会遍历整个数组然后求出元素个数,因此复杂度是O(n)。那实际情况是不是这样呢?我们回到count的实现来看一下,通过源码可以发现,对于数组的count操作,函数最终的路径是zif_count-> php_count_recursive-> zend_hash_num_elements,而zend_hash_num_elements的行为是 return ht->nNumOfElements,可见,这是一个O(1)而不是O(n)的操作。实际上,数组在php底层就是一个hash_table,对于hash表,zend中专门有一个元素nNumOfElements记录了当前元素的个数,因此对于一般的count实际上直接就返回了这个值。由此,我们得出结论: count是O(1)的复杂度,和具体数组的大小无关。

  非数组类型的变量,count的行为时怎样?对于未设置变量返回0,而像int、double、string等则会返回1

  strlen

  Strlen用于返回一个字符串的长度。那么,他的实现原理是如何的呢?我们都知道在c中strlen是一个o(n)的函数,会顺序遍历字符串直到遇到,然后出长度。Php中是否也这样呢?答案是否定的,php里字符串是用一个复合结构来描述,包括指向具体数据的指针和字符串长度(和c++中string类似),因此 strlen就直接返回字符串长度了,是常数级别的操作。另外,对于非字符串类型的变量调用strlen,它会首先将变量强制转换为字符串再求长度,这点需要注意。

  isset和array_key_exists

  这两个函数最常见的用法都是判断一个 key是否在数组中存在。但是前者还可以用于判断一个变量是否被设置过。如前文所述,isset并非真正的函数,因此它的效率会比后者高很多。推荐用它代替array_key_exists。

  array_push和array[]

  两者都是往数组尾部追加一个元素。不同的是前者可以一次push多个。他们最大的区别在于一个是函数一个是语言结构,因此后者效率要更高。因此如果只是普通的追加元素,建议使用array []。

  rand和mt_rand

  两者都是提供产生随机数的功能,前者使用 libc标准的rand。后者用了 Mersenne Twister 中已知的特性作为随机数发生器,它可以产生随机数值的平均速度比 libc 提供的 rand() 快四倍。因此如果对性能要求较高,可以考虑用mt_rand代替前者。我们都知道,rand产生的是伪随机数,在C中需要用srand显示指定种子。但是在php中,rand会自己帮你默认调用一次srand,一般情况下不需要自己再显示的调用。需要注意的是,如果特殊情况下需要调用srand时,一定要配套调用。就是说srand对于rand,mt_srand对应srand,切不可混合使用,否则是无效的。

  sort和 usort

  两者都是用于排序,不同的是前者可以指定排序策略,类似我们C里面的qsort和C++的sort。在排序上两者都是采用标准的快排来实现,对于有排序需求的,如非特殊情况调用php提供的这些方法就可以了,不用自己重新实现一遍,效率会低很多。原因见前文对于用户函数和内置函数的分析比对。

  urlencode和rawurlencode

  这两个都是用于 url编码, 字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数。两者唯一的区别在于对于空格,urlencode会编码为+,而 rawurlencode会编码为%20。一般情况下除了搜索引擎,我们的策略都是空格编码为%20。因此采用后者的居多。注意的是encode和 decode系列一定要配套使用。

  strcmp系列函数

  这一系列的函数包括strcmp、 strncmp、strcasecmp、strncasecmp,实现功能和C函数相同。但也有不同,由于php的字符串是允许出现,因此在判断的时候底层使用的是memcmp系列而非strcmp,理论上来说更快。另外由于php直接能获取到字符串长度,因此会首先这方面的检查,很多情况下效率就会高很多了。

  is_int和is_numeric

  这两个函数功能相似又不完全相同,使用的时候一定需要注意他们的区别。Is_int:判断一个变量类型是否是整数型,php变量中专门有一个字段表征类型,因此直接判断这个类型即可,是一个绝对 O(1)的操作 Is_numeric:判断一个变量是否是整数或数字字符串,也就是说除了整数型变量会返回true之外,对于字符串变量,如果形如”1234”,”1e4”等也会被判为true。这个时候会遍历字符串进行判断。

  总结及建议

  总结:

  通过对函数实现的原理分析和性能测试,我们总结出以下一些结论

  1. Php的函数调用开销相对较大。

  2. 函数相关信息保存在一个大的hash_table中,每次调用时通过函数名在hash表中查找,因此函数名长度对性能也有一定影响。

  3. 函数返回引用没有实际意义

  4. 内置php函数性能比用户函数高很多,尤其对于字符串类操作。

  5. 类方法、普通函数、静态方法效率几乎相同,没有太大差异

  6. 除去空函数调用的影响,内置函数和同样功能的C函数性能基本差不多。

  7. 所有的参数传递都是采用引用计数的浅拷贝,代价很小。

  8. 函数个数对性能影响几乎可以忽略

  建议:

  因此,对于php函数的使用,有如下一些建议

  1. 一个功能可以用内置函数完成,尽量使用它而不是自己编写php函数。

  2. 如果某个功能对性能要求很高,可以考虑用扩展来实现。

  3. Php函数调用开销较大,因此不要过分封装。有些功能,如果需要调用的次数很多本身又只用1、2行代码就行实现的,建议就不要封装调用了。

  4. 不要过分迷恋各种设计模式,如上一条描述,过分的封装会带来性能的下降。需要考虑两者的权衡。Php有自己的特点,切不可东施效颦,过分效仿java的模式。

  5. 函数不宜嵌套过深,递归使用要谨慎。

  6. 伪函数性能很高,同等功能实现下优先考虑。比如用isset代替array_key_exists

  7. 函数返回引用没有太大意义,也起不到实际作用,建议不予考虑。

  8. 类成员方法效率不比普通函数低,因此不用担心性能损耗。建议多考虑静态方法,可读性及安全性都更好。

  9. 如不是特殊需要,参数传递都建议使用传值而不是传引用。当然,如果参数是很大的数组且需要修改时可以考虑引用传递。

时间: 2024-09-11 20:29:53

百度工程师讲PHP函数的实现原理及性能分析(三)的相关文章

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

  这篇文章主要介绍了百度工程师讲PHP函数的实现原理及性能分析(一),需要的朋友可以参考下 前言 在任何语言中,函数都是最基本的组成单元.对于php的函数,它具有哪些特点?函数调用是怎么实现的?php函数的性能如何,有什么使用建议?本文将从原理出发进行分析结合实际的性能测试尝试对这些问题进行回答,在了解实现的同时更好的编写php程序.同时也会对一些常见的php函数进行介绍. php函数的分类 在php中,横向划分的话,函数分为两大类: user function(内置函数) 和internal

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

  这篇文章主要介绍了百度工程师讲PHP函数的实现原理及性能分析(二),本文讲解了类方法.性能对比.内置函数和用户函数性能对比等内容,需要的朋友可以参考下 类方法 类方法其执行原理和用户函数是相同的,也是翻译成opcodes顺次调用.类的实现,zend用一个数据结构zend_class_entry来实现,里面保存了类相关的一些基本信息.这个entry是在php编译的时候就已经处理完成. 在 zend_function的common中,有一个成员叫做scope,其指向的就是当前方法对应类的zend

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

前言 在任何语言中,函数都是最基本的组成单元.对于php的函数,它具有哪些特点?函数调用是怎么实现的?php函数的性能如何,有什么使用建议?本文将从原理出发进行分析结合实际的性能测试尝试对这些问题进行回答,在了解实现的同时更好的编写php程序.同时也会对一些常见的php函数进行介绍. php函数的分类 在php中,横向划分的话,函数分为两大类: user function(内置函数) 和internal function(内置函数).前者就是用户在程序中自定义的一些函数和方法,后者则是php本身

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

常用php函数实现及介绍 count count是我们经常用到的一个函数,其功能是返回一个数组的长度. count这个函数,其复杂度是多少呢? 一种常见的说法是count函数会遍历整个数组然后求出元素个数,因此复杂度是O(n).那实际情况是不是这样呢?我们回到count的实现来看一下,通过源码可以发现,对于数组的count操作,函数最终的路径是zif_count-> php_count_recursive-> zend_hash_num_elements,而zend_hash_num_elem

openSessionInView的使用原理及性能分析

看到好多项目中用到了openSessionInView,这样的做法无非是开发方便,可以在JSP页面中操作数据库层方面的业务.下边说下openSessionInView的用法及性能问题. 使用: 1.增加一个Filter,该Filter用来控制事务及数据库的连接管理,代码如下: SessionFactory sessionFactory = lookupSessionFactory(request); Session session = null; boolean participate = fa

深入分析MySQL索引结构原理、性能分析与优化详解

第一部分:基础知识: 索引 官方介绍索引是帮助MySQL高效获取数据的数据结构.笔者理解索引相当于一本书的目录,通过目录就知道要的资料在哪里,不用一页一页查阅找出需要的资料.关键字index --------------------- 唯一索引 强调唯一,就是索引值必须唯一,关键字unique index 创建索引: 1.create unique index 索引名 on 表名(列名); 2.alter table 表名 add unique index 索引名 (列名); 删除索引: 1.

收藏好文章 PHP函数的实现原理

作者:HDK (百度)  前言 在任何语言中,函数都是最基本的组成单元.对于php的函数,它具有哪些特点?函数调用是怎么实现的?php函数的性能如何,有什么使用建议?本文将从原理出发进行分析结合实际的性能测试尝试对这些问题进行回答,在了解实现的同时更好的编写php程序.同时也会对一些常见的php函数进行介绍. php函数的分类 在php中,横向划分的话,函数分为两大类: user function(内置函数) 和internal function(内置函数).前者就是用户在程序中自定义的一些函数

百度工程师告诉你网页里注释的内容是否会被抓取

摘要: 很多站长都知道网页代码里面有注释代码这么个东西,其形式是!-注释内容-,在HTML里面注释的内容出现在网页源代码,而用户浏览网页的过程中是看不到的.因为注释内容在源代码展现 很多站长都知道网页代码里面有注释代码这么个东西,其形式是<!-注释内容->,在HTML里面注释的内容出现在网页源代码,而用户浏览网页的过程中是看不到的.因为注释内容在源代码展现又不会影响页面内容,所以很多人觉得蜘蛛会抓取注释信息并参与到网页的分析排名,于是在网页加入大量的注释内容,甚至直接在注释里面堆砌关键词. 那

CLR 中匿名函数的实现原理浅析

函数 CLR 中匿名函数的实现原理浅析 C# 2.0中提供了通过delegate实现匿名函数功能,能有效地减少用户的薄记代码工作,例如 以下为引用: ...button1.Click += new EventHandler(button1_Click);...void button1_Click(Object sender, EventArgs e) { // Do something, the button was clicked...}... 可以被简化为直接使用匿名函数构造,如 以下为引用