PHP虽然是世界上最好的语言,但是它本身作为一门脚本语言,其运行效率一直被人们所诟病。
作为以PHP为开发语言的应用程序而言,PHP程序的性能能影响到整个架构性能的百分之30左右,不会超过百分之50,其余的是硬件的、操作系统的、存储的等等其他性能优化;因此,PHP程序的性能好坏,对于整个系统架构而言,还是很重要的。
PHP的性能优化分为一下三个层次:
这三个层次性能优化的难度依次上升,效果却依次降低。在此,我们重点讨论前两种层次。
PHP代码的优化
多使用PHP内置的函数,少使用PHP代码,且精简PHP代码
PHP的执行流程为:
这个原理是很简单的,PHP是解释型语言,PHP代码得经过好几步转化才能变成最终的机器码,假如PHP代码写的很多,不够精简,转化的步骤就会变长,自然会影响PHP程序的性能。而PHP内置的函数是由C语言编写的,运行速度自然快。
PHP内置函数的执行效率也有优先级,可以尽量使用快的
这个原因也是显而易见的,虽然都是C语言写的程序,但是C实现的方式还是不同的,有的实现方式快一些,有的实现的慢一些,所以调用快的效率肯定会高一点。
例如:
- array_key_exists效率要比in_array高
- require比require_once效率高
- 单引号''比双引号""效率高
减少PHP魔法函数的使用
PHP的魔法函数用起来很爽,但是既然用的这么爽,那么PHP在底层肯定帮你做了诸多事情,做的这么一堆事情,不能不消耗性能吧。
PHP魔法函数为了让程序员爽,在语言级别帮程序猿做了很多,会带啦性能开销,我们应该看情况酌情使用。
不要使用错误抑制符@
@错误抑制符这玩意儿的实现原理和魔法函数差不多,都是方便了程序猿苦了自己;原理也很简单,就是在添加了错误@符号的前面和后面添加了Opcode,Opcode的作用就是和error_reporting忽略错误一样一样的,然后在添加了@符号的代码之后再添加上一些Opcode,将错误等级恢复。
可以用PHP的Opcode查看扩展vld来查看添加了@符号的代码情况。(vld的使用也很简单,就俩指令vld.active=1和vld.execute=0., vld.active=1表示想要用扩展,vld.execute=0.表示只是查看Opcode代码,vld.execute=1.表示要执行php程序。
1 | 1` ```` ` |
php -vld.active=1 -vld.execute=0 xxx.php)
合理使用PHP内存,释放掉没用的变量
要尽量合理的使用内存,例如:
- 从数据库中取字段,只取某个字段,就不要取出全部字段。 select xxx 和 select * 的区别
- 读取文件,文件使用完后,文件close的问题
- 使用unset及时释放掉无用的变量。(但是也会有unset不掉的情况)
尽量减少使用正则表达式
正则表达式需要回溯,当正则表达式越长,它回溯的开销就会越大,优化表达式也是个技术活儿,所以建议尽量使用PHP内置的处理函数来替代。
避免循环内做重复的计算
例如:
1
2
3
4
5
6
7 1$str = "hello world";
2for ($i = 0; $i<strlen($str); $i ++)
3{
4 //do something
5}
6
7
strlen($str)是不是被重复计算了?有意义吗?写在外边不好吗?
避免数据密集型计算
PHP是由C语言来实现的,PHP本身在处理一些计算的时候,额外的开销是很大的,例如它的变量寄存、语言处理,都需要C来实现…PHP的“慢”,不是由于一些特性而“慢”,是整体就慢。所以在处理一些大批量数据例如大批量日志处理,大批量数据分析的时候,是十分不适合的,和C等语言比起来不是一个数量级。
PHP的语言特性决定了PHP不适合做大数据量的计算。
PHP适合做的事:
PHP适合做一个纽带,适合做一些字符串、文本处理。
使用Opcode cache
Opcode是整个PHP中最接近机器码的地方,假如我们对Opcode做一下缓存,就节约了PHP代码解析、编译的开销,在此,我们可以使用一些扩展来对Opcode进行缓存
- APC。(已经不更新)
- 鸟哥的yac。
PHP周边性能优化
以上就是PHP周边的环境。只有PHP周边的环境也得到了很好的性能优化,才能将PHP的系统架构发挥到极致。
不要使用过多的IO
PHP场景的性能开销次序为:读取内存 < 读取数据库 < 读取文件 < 读取网络数据
PHP是不适合编写IO密集型的程序。
优化网络请求
设置超时时间
- 连接超时 200ms
- 读超时 800ms
- 写超时 500ms
将串行请求并行化
- 使用curl_multi_*()的函数代替curl
- 使用swoole扩展(比 curl_multi还要好)
合理的将PHP接口输出压缩
使用gzip可以将PHP接口输出压缩,提高我们的IO,但是压缩的过程需要额外的计算消耗,需要消耗部分CPU性能,需要合理使用;当数据量小于几十kb的时候,用gzip还不如不用,当gzip数据大于100k的时候,压缩是合理的,而且压缩的程度还和数据重复的个数有关,如果重复的多,gizp就压缩的小,如果重复的少,gzip压缩的就稍微大点儿。
最后的解决方案
使用性能优化分析工具
- Facebook的XHPorf
- 压力测试工具Apache的ab
- opcode代码分析工具vld
用PHP扩展代替部分逻辑
这个不用多说,很多大公司都是这么做的。
把很多PHP的library做成.so文件。
使用PHP7
HHVM是由Facebook推出的,用来提升PHPruntime效率的,效果十分明显。但是,就PHP7而言,官方觉得PHP7的engine更胜一筹,所以,如果想要整体提高性能,升级PHP7还是必要的。