PHP的性能优化⽅法总结
什么情况之下,会遇到PHP性能问题?
1:PHP语法使⽤不恰当。
2:使⽤PHP语⾔做了它不擅长的事情。
3:使⽤PHP语⾔连接的服务不给⼒。
4:PHP⾃⾝的短板(PHP⾃⾝做不了的事情)。
5:我们也不知道的问题?(去探索、分析到解决办法,提升开发境界)。
对线上站点做压⼒测试的时候,我们⼀定要将请求数和并发数,特别是并发数要设置的⽐较低,我们不能对线上的⽹站造成压⼒问题,不管是⾃⼰的还是别⼈的。
PHP性能问题⼀般不会超过占整个项⽬性能的50%,⼀般在30%~40%。
PHP性能问题的解决⽅向,三个层级
1:PHP语⾔级的性能优化,指的是PHP语法基本功能,这部分优化⽐较简单易见、快速可⾏,⽐较快速看到效果。
a:少写PHP的代码,多⽤PHP⾃⾝能⼒解决问题。
性能问题
⾃写代码冗余较多,可读性不佳,并且性能低,如代码很长很长...PHP代码越长PHP的执⾏效率越慢。
为什么性能低?
PHP代码需要解析编译为C语⾔,底层C语⾔⼜要编译成汇编语⾔机器语⾔才能执⾏,这个过程在每次请求过来之后都要处理⼀遍,所以开销很⼤(项⽬变⼤的话...)。
解决⽅法:
多使⽤PHP内置的变量、常量、函数。我们⽤PHP代码实现的功能和使⽤PHP内置的函数实现的同样功能差别是有的。
b:PHP内置函数的性能优劣。
情况描述
PHP内置函数之间依然存在快慢差别;少⽤PHP魔术⽅法;
建议:
多去了解PHP内置函数的执⾏实现复杂度。
测试⽅法:⽐较效率测试,如⽤microtime()函数,取差值,精确到毫秒级别;Linux的time命令可以查看开销。
c:产⽣额外开销的错误抑制符号“@”,最好别⽤(不管是性能优化和项⽬的健壮性等⽅⾯)。
@的逻辑是在代码前和代码结束后增加了Opcode,Opcode的作⽤就是忽略报错,其实就是相当于增加
了error_reporting设置,等级报错为忽略(vld扩展可以查看被隐藏的Opcode);
d:合理使⽤内存。
情况描述:
PHP有内存回收机制保底,但是也⼩⼼使⽤内存;
建议:
利⽤unset()及时释放不使⽤的内存,⽐如⼀些数据库多余字段(注意:unset()有时会出现注销不掉的情况)
e:尽量少⽤正则表达式。
情况描述:
正则表达式的开销⼤,使⽤起来简单,但是性能低因为,正则表达式需要回溯;正则表达式越长,回溯的开销越⼤,优化正则表达式是需要技术⽔平的,正则技术不达标,不要乱⽤正则。
f:避免在循环内做运算。
情况描述:
循环内的计算式将被重复计算(我们在for循环或者while循环,会有重复计算,影响性能问题)。
举例:
错误⽤法:
$str = "hello world";
for($i = 0; $i < strlen($str); $i ++){ ...}
正确⽤法:
$str = "hello world";
$strlen = strlen($str);
for($i = 0; $i < $strlen; $i++){...}
g:减少计算密集型业务
情况描述:
PHP不适合密集型(⼤数据量)运算的场景。
为什么?
PHP的语⾔特性决定PHP不适合做⼤数据量运算,PHP语⾔由C写的,PHP处于C基础之上,PHP的所有运算处理流程需要转化为C语
⾔,PHP和C想⽐性能肯定输了,并且
PHP语⾔还有⼀些环境问题、语⾔特性,相⽐于C⽽⾔的开销要⼤很多的。PHP⼀段很长的代码,可能C很短就实现了...
PHP适合场景:
适合衔接WebServer与后端服务,WebServer来了请求交给PHP,PHP做⼀些校验、⼀些初始化数据处理,将请求转发交给后端,等待后台响应,后端可能是缓存、DB等其他业务,
后端响应之后,PHP再作为纽带,将信息传递给WebServer,这是PHP擅长的。PHP也擅长做UI呈现,也就是配合模板引擎做模板输出,其实就是⼀些字符串⽂本处理。
h:务必使⽤带引号字符串做键值(数组的Key字段)。
情况描述
PHP会将没有使⽤引号的键值当做常量,产⽣查常量的开销,如果查到了常量有这个字符串,那么就把常量作为这个值了。
建议:
严格使⽤引号作为键值,单引号即可。
2:PHP周边的性能优化:(PHP前⾯有WebServer,后⾯有数据库)
3:PHP语⾔⾃⾝的分析、优化(底层C级别的优化)
补充:
1:尽量静态化:
如果⼀个⽅法能被静态,那就声明它为静态的,速度可提⾼1/4,甚⾄我测试的时候,这个提⾼了近三倍。
当然了,这个测试⽅法需要在⼗万级以上次执⾏,效果才明显。
其实静态⽅法和⾮静态⽅法的效率主要区别在内存:静态⽅法在程序开始时⽣成内存,实例⽅法在程序运⾏中⽣成内存,所以静态⽅法可以直接调⽤,实例⽅法要先成⽣实例,通过实例调⽤⽅法,静态速度很快,但是多了会占内存。
任何语⾔都是对内存和磁盘的操作,⾄于是否⾯向对象,只是软件层的问题,底层都是⼀样的,只是实现⽅法不同。静态内存是连续的,因为是在程序开始时就⽣成了,⽽实例申请的是离散的空间,所以当然没有静态⽅法快。
静态⽅法始终调⽤同⼀块内存,其缺点就是不能⾃动进⾏销毁,⽽是实例化可以销毁。
2.销毁变量去释放内存,特别是⼤的数组;
数组和对象在php特别占内存的,这个由于php的底层的zend引擎引起的,
⼀般来说,PHP数组的内存利⽤率只有 1/10, 也就是说,⼀个在C语⾔⾥⾯100M 内存的数组,在PHP⾥⾯就要1G。
特别是在PHP作为后台服务器的系统中,经常会出现内存耗费太⼤的问题。
以下是我在其他博⽂收集的
1、如果能将类的⽅法定义成static,就尽量定义成static,它的速度会提升将近4倍。
2、$row[’id’] 的速度是$row[id]的7倍。
3、注销那些不⽤的变量尤其是⼤数组,以便释放内存。
4、尽量避免使⽤__get,__set,__autoload。
5、require_once()代价昂贵。
6、include⽂件时尽量使⽤绝对路径,因为它避免了PHP去include_path⾥查⽂件的速度,解析操作系统路径所需的时间会更少。
7、如果你想知道脚本开始执⾏(译注:即服务器端收到客户端请求)的时刻,使⽤$_SERVER[‘REQUEST_TIME’]要好于time()
8、函数代替正则表达式完成相同功能。
9、str_replace函数⽐preg_replace函数快,但strtr函数的效率是str_replace函数的四倍。
10、如果⼀个字符串替换函数,可接受数组或字符作为参数,并且参数长度不太长,那么可以考虑额外写⼀段替换代码,使得每次传递参数是⼀个字符,⽽不是只写⼀⾏代码接受数组作为查询和替换的参数。
11、使⽤选择分⽀语句(译注:即switch case)好于使⽤多个if,else if语句。
12、⽤@屏蔽错误消息的做法⾮常低效,极其低效。
13、打开apache的mod_deflate模块,可以提⾼⽹页的浏览速度。
14、数据库连接当使⽤完毕时应关掉,不要⽤长连接。
15、在⽅法中递增局部变量,速度是最快的。⼏乎与在函数中调⽤局部变量的速度相当。递增⼀个全局变量要⽐递增⼀个局部变量慢2倍。递增⼀个对象属性(如:$this->prop++)要⽐递增⼀个局部变量慢3倍。递增⼀个未预定义的局部变量要⽐递增⼀个预定义的局部变量慢9⾄10倍。
16、仅定义⼀个局部变量⽽没在函数中调⽤它,同样会减慢速度(其程度相当于递增⼀个局部变量)。PHP⼤概会检查看是否存在全局变量。
17、⽅法调⽤看来与类中定义的⽅法的数量⽆关,因为我(在测试⽅法之前和之后都)添加了10个⽅法,但性能上没有变化。
18、派⽣类中的⽅法运⾏起来要快于在基类中定义的同样的⽅法。
19、调⽤带有⼀个参数的空函数,其花费的时间相当于执⾏7⾄8次的局部变量递增操作。类似的⽅法调⽤所花费的时间接近于15次的局部变量递增操作。
20、Apache解析⼀个PHP脚本的时间要⽐解析⼀个静态HTML页⾯慢2⾄10倍。尽量多⽤静态HTML页⾯,少⽤脚本。
21、除⾮脚本可以缓存,否则每次调⽤时都会重新编译⼀次。引⼊⼀套PHP缓存机制通常可以提升25%⾄100%的性能,以免除编译开销。
22、尽量做缓存,可使⽤memcached。memcached是⼀款⾼性能的内存对象缓存系统,可⽤来加速动态Web应⽤程序,减轻数据库负载。对运算码 (OP code)的缓存很有⽤,使得脚本不必为每个请求做重新编译。
23、当操作字符串并需要检验其长度是否满⾜某种要求时,你想当然地会使⽤strlen()函数。此函数执⾏起来相当快,因为它不做任何计算,只返回在zval 结构(C的内置数据结构,⽤于存储PHP变量)中存储的已知字符串长度。但是,由于strlen()是函数,多多少少会有些慢,因为函数调⽤会经过诸多步骤,如字母⼩写化(译注:指函数名⼩写化,PHP不区分函数名⼤⼩写)、哈希查,会跟随被调⽤的函数⼀起执⾏。在某些情况下,你可以使⽤isset() 技巧加速执⾏你的代码。
24、当执⾏变量$i的递增或递减时,$i++会⽐++$i慢⼀些。这种差异是PHP特有的,并不适⽤于其他语⾔,所以请不要修改你的C或Java代码并指望它们能⽴即变快,没⽤的。++$i更快是因为它只需要3条指令(opcodes),$i++则需要4条指令。后置递增实际上会产⽣⼀个临时变量,这个临时变量随后被递增。⽽前置递增直接在原值上递增。这是最优化处理的⼀种,正如Zend的PHP优化器所作的那样。牢记这个优化处理不失为⼀个好主意,因为并不是所有的指令优化器都会做同样的优化处理,并且存在⼤量没有装配指令优化器的互联⽹服务提供商(ISPs)和服务器。
25、并不是事必⾯向对象(OOP),⾯向对象往往开销很⼤,每个⽅法和对象调⽤都会消耗很多内存。
26、并⾮要⽤类实现所有的数据结构,数组也很有⽤。
27、尽量采⽤⼤量的PHP内置函数。
28、如果在代码中存在⼤量耗时的函数,你可以考虑⽤C扩展的⽅式实现它们。
29、评估检验(profile)你的代码。检验器会告诉你,代码的哪些部分消耗了多少时间。Xdebug调试器包含了检验程序,评估检验总体上可以显⽰出代码的瓶颈。
30、mod_zip可作为Apache模块,⽤来即时压缩你的数据,并可让数据传输量降低80%。
31、在可以⽤file_get_contents替代file、fopen、feof、fgets等系列⽅法的情况下,尽量⽤file_get_contents,因为他的效率⾼得多!但是要注意file_get_contents在打开⼀个URL⽂件时候的PHP版本问题;
fopen绝对路径32、尽量的少进⾏⽂件操作,虽然PHP的⽂件操作效率也不低的;
33、优化Select SQL语句,在可能的情况下尽量少的进⾏Insert、Update操作(在update上,我被恶批过);
34、循环内部不要声明变量,尤其是⼤变量:对象(这好像不只是PHP⾥⾯要注意的问题吧?);
35、多维数组尽量不要循环嵌套赋值;
36、在可以⽤PHP内部字符串操作函数的情况下,不要⽤正则表达式;
37、foreach效率更⾼,尽量⽤foreach代替while和for循环;
38、⽤单引号替代双引号引⽤字符串;
39、“⽤i+=1代替i=i+1。符合c/c++的习惯,效率还⾼”;
40、对global变量,应该⽤完就unset()掉;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论