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
  • requirerequire_once 效率高
  • 单引号''比双引号""效率高

减少PHP魔法函数的使用

PHP的魔法函数用起来很爽,但是既然用的这么爽,那么PHP在底层肯定帮你做了诸多事情,做的这么一堆事情,不能不消耗性能吧。
PHP魔法函数为了让程序员爽,在语言级别帮程序猿做了很多,会带啦性能开销,我们应该看情况酌情使用。

不要使用错误抑制符@

@错误抑制符这玩意儿的实现原理和魔法函数差不多,都是方便了程序猿苦了自己;原理也很简单,就是在添加了错误@符号的前面和后面添加了Opcode,Opcode的作用就是和error_reporting忽略错误一样一样的,然后在添加了@符号的代码之后再添加上一些Opcode,将错误等级恢复。

可以用PHP的Opcode查看扩展vld来查看添加了@符号的代码情况。(vld的使用也很简单,就俩指令vld.active=1vld.execute=0., vld.active=1表示想要用扩展,vld.execute=0.表示只是查看Opcode代码,vld.execute=1.表示要执行php程序。``php -vld.active=1 -vld.execute=0 xxx.php)

合理使用PHP内存,释放掉没用的变量

要尽量合理的使用内存,例如:

  • 从数据库中取字段,只取某个字段,就不要取出全部字段。 select xxx 和 select * 的区别
  • 读取文件,文件使用完后,文件close的问题
  • 使用unset及时释放掉无用的变量。(但是也会有unset不掉的情况)

尽量减少使用正则表达式

正则表达式需要回溯,当正则表达式越长,它回溯的开销就会越大,优化表达式也是个技术活儿,所以建议尽量使用PHP内置的处理函数来替代。

避免循环内做重复的计算

例如:

1
2
3
4
5
$str = "hello world";
for ($i = 0; $i<strlen($str); $i ++)
{
//do something
}

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还是必要的。