PHP 性能优化在中大型项目当中是非常重要的一件事情。
PHP 性能优化分为代码级和配置级两个部分。
一、PHP 代码级优化建议
1)用单引号代替双引号
因为 PHP 会在双引号包含的字符串中搜索变量,单引号不会。在单引号当中,PHP 不会自动搜索变量、转义字符等。因此效率上快很多。特别是在一些大内容的字符串的情景下,单引号性能更优异。
2)
$row['id']
的速度是$row[id]
的 7 倍。
在一些旧版不严格的 PHP 当中,$row['id']
写成 $row[id]
也是能正确解析的。新版这样会提示 notice 错误。
3)使用 for 对数组循环之前确定数组元素的长度
虽然像 count、strlen 这样的操作时间复杂度是O(1),不会有太大的性能消耗。当然避免每次都循环计算是一个良好的习惯。
4)unset 那些不用的变量及大数组。
大小项目当中性能可能并不明显。但是在大项目且并发量高的时候,变量占用的内存如果不及时注销回收,会导致内存负载很高。
5)尽量使用伪函数(语言结构 )
常用的语言结构有 echo、isset、unset 等。它们比函数性能要高很多。常见的 isset 替换掉 array_key_exists。如何判断一个方法是语言结构还是普通方法?
方式一:
<?php
var_dump(function_exists('echo'));
方式二:
// 在 PHP 命令行操作
$ php --rf echo
6)类静态方法比普通类成员方法性能好。
这个性能差异在旧版表现明显,在 PHP 5.6+ 之后,这个差异并不是很明显了。当然,静态方法在调用的时候更易操作。
7)尽量避免使用魔术方法。
通过对魔术方法测试魔术方法比普通的方法性能在压力很高的环境下相差成倍呈现。
8)加载文件时尽量使用绝对路径。
PHP 加载相对路径会从可能的库位置进行尝试加载。可能的库位置由 php.ini 配置文件当中的 include_path
配置决定。这里的路径配置越多,那么相对路径的加载就会越慢。
9)函数代替正则表达式完成相同的功能。
与之相关的功能有:strtok、strstr、strpos、str_replace、substr、explode、implode。
10)尽量避免使用 @ 屏蔽错误消息的做法。
我们应该使用使用 error_reporting(0) 关闭错误,使用使用 error_log 把错误写入日志文件。
11)尽量避免程序抛出 notice 错误消息。
错误消息对性能影响很大。即使通过 error_reporting(0) 关闭了也不行。所以,我们要尽量避免错误的产生。
12)能用 PHP 内置方法解决就不要自己用代码实现
内置方法比自定义方法速度快。在自己实现之前,请检查 PHP 内置方法已经提供。
13)用尽量少的代码实现功能。
很明显,代码越长不仅不易维护,而且 PHP 词法解析器与语法语法解析器会用更多的时间去翻译,挺累的。
14)自增/自减局部变量比全局变量快。
本身从变量所处内存位置亦可知局部变量比全局变量要快。
15)派生类中的方法运行起来要快于在基类中定义的同样方法。
从 PHP 原理来说,首先从当前类查找该方法,找不到再找父类。假如此时当前类是一个多级的子孙类。那么,就会导致向上查找。从而性能会下降。
16)并非要用类实现所有的数据结构,数组也很有用。
类比对象会消耗更多的内存。很多人在 PHP 开发过程中会过度的像 Java 这种语言一样面向对象。把一些复杂参数的传递封装成一个对象。其实大多数情况下没有必要。直接传数据就很好。性能表现也非常好。
17)尽量少的进行文件操作。
在任何语言下,对文件的操作都会对性能产生影响。操作的文件越多性能越差。毕竟,最终性能都会反应在系统 IO 上。
18)尽量使用 file_get_contents/file_put_contents 代替 fopen/fget 等相关的文件读写函数。除非需要对文件更精细的操作。
19)尽量少的对数据库进行 INSERT/UPDATE/DELETE 操作。
众所周知,INSERT/UPDATE/DELETE 对数据库造成 IO 压力。操作越频繁,压力越大。通常在一个项目中 20% 是写入操作,80% 是读操作。这就是所谓的二八原则。
20)对函数/方法内 global 的变量,应该用完就 unset 掉。
global 的变量,unset 的时候只会在当前函数或方法内部被清除掉。并不会把全局的变量给清除。
21)能用缓存的地方尽量使用缓存。
众所周知,缓存可以帮助我们挡掉一部分调用数据库以及逻辑运算部分的工作。所以,性能肯定是快快的。
22)"用 i+=1代替 i=i+1。符合 c/c++ 的习惯,效率还高 "。
23)多维数组尽量不要循环嵌套赋值。
翻译过来就是不要在循环过程中动态在数据内部创建一个元素。然后,再次循环在的时候在这个元素内部再动态创建一个元素。
24)如不是特殊需要,参数传递都建议使用传值而不是传引用。当然,如果参数是很大的数组且需要修改时可以考虑引用传递。
二、PHP 配置级优化建议
- 禁用高风险 PHP 函数
disable_functions = 该选项可以设置哪些 PHP 函数是禁止使用的。PHP 中有一些函数的风险性还是相当大的,可以直接执行一些系统级脚本命令。如果允许这些函数执行,当 PHP 程序出现漏洞时,损失是非常严重的!以下我们给出推荐的禁用函数设置:
disable_functions = phpinfo,passthru,exec,system,popen,chroot,escapeshellcmd,escapeshellarg,shell_exec,proc_open,proc_get_status
需注意:如果您的服务器中含有一些系统状态检测的 PHP 程序,则不要禁用shell_exec,proc_open,proc_get_status 等函数。
- 优化 PHP 脚本执行时间
max_execution_time = 30
该选项设定 PHP 程序的最大执行时间,如果一个 PHP 脚本被请求,且该 PHP 脚本在 max_execution_time 时间内没能执行完毕,则 PHP 不再继续执行,直接给客户端返回超时错误。没有特殊需要该选项可保持默认设置 30秒。如果您的 PHP 脚本确实需要长执行时间则可以适当增大该时间设置。
- 优化 PHP 脚本处理内存占用
memory_limit = 8M
该选项指定 PHP 脚本处理所能占用的最大内存,默认为 8MB,如果您的服务器内存为 1GB 以上,则该选项可以设置为 12MB 以获得更快的 PHP 脚本处理效率。
如果此值设置过小,那么一些大型的耗时的框架,比如像 Laravel/wordpress 就会导致报 "Fatal Error: Allowed memory size of xxxxxx bytes exhausted " 的错误。
- PHP上传文件大小限制:
upload_max_filesize = 2M
该选项设定PHP所能允许最大上传文件大小,默认为 2MB。根据实际应用需求,可以适当增大该设置。一定要谨防此值设置过大,导致遭遇大文件上传把服务器资源吃尽导致服务器瘫痪。
比如,我们设置此值允许最大上传 1GB。一个普通用户上传一个 1GB 的文件需要 30 分钟。那么假如一个恶意用户模拟 1000 个正常用户上传文件。那么此时服务器同一时刻会面临 1000 上传与服务器对接。造成服务器 30 分钟内不能响应其他正常请求。导致服务器陷入瘫痪之境。
- Session存储介质
session.save_path
在小应用当中,通常 session 都存储到服务器文件当中。就是由此选项决定。如果你用的是一些 PHP 框架。那么,可能此值会在框架当中被修改。
一般大型应用会将 session 写入到类似如 Redis 这样的缓存当中。以此降低 session 写入/删除时对服务器性能造成 IO 压力。