原文链接:https://blog.csdn.net/ligupeng7929/article/details/87883956
1.什么情况下会碰到PHP性能问题?
1>PHP语法使用的不恰当
2>使用PHP做了它不擅长的事情
3>用PHP语言连接的服务不给力
4>php自身的短板
5>我也不知道的问题
2.PHP的性能问题,一般的话不会占到整体项目性能问题比例的一半
3.PHP的性能问题解决方向:PHP语言级的性能优化=》PHP周边问题的性能优化=》PHP语言自身分析、优化,难度从易到难
压力测试工具:ab 由Apache提供的压力测试软件,安装apache服务器会自带该压测软件
如何使用:
./ab -n1000(请求数) -c100(并发数) http://www.baidu.com/ (url目标压测地址)
优化点:少些代码,多用PHP自身能力
性能问题:自身代码冗余较多,可读性不佳,而且性能低
为什么性能低:PHP代码需要编译解析为底层C语言,C语言再次编译成汇编语言、机器语言才能执行,这一过程在每次请求都会处理一遍,开销大
好的方法:多使用PHP内置变量、常量、函数
PHP代码运行流程:
*.PHP-》Scanner(通过PHP底层的zend引擎,逐行扫描分析保存为zend引擎自己能识别的语法)=》Exprs(通过解析成Opcodes)=>Opcodes(即将拿去执行的机器码)
如果直接用PHP内置的函数,首先在扫描过程中就少很多,代码行数少,到zend这层也是更快的,因为用php自身的函数就是相当用zend引擎自身的功能,相应产出的opcode就少一些,所以执行的块,现在很多PHP的缓存服务就是缓存opcodes这一环节
优化点:PHP内置函数的性能优劣
情况描述:PHP内置函数之间依然存在快慢差异
好的意见:多去了解PHP内置函数的时间复杂度
优化点:尽可能少用魔法函数
情况描述:性能不佳
为什么性能低:为了省事,PHP语言为你做了很多
例如:使用了__get() 循环10万 (85ms) 不使用 循环10万 (53ms)
优化点:产生额外开销的错误抑制符@
描述:在代码开始前、结束后,增加了Opcode,前将报错的等级忽略,后将报错的等级恢复
vld-PHP Opcode查看扩展 主要作用是将opcode的代码演示出来
vld扩展主要的两个参数列表
-dvld.active 默认为0。代表是否在运行PHP文件是激活vld扩展,
-dvld.execute 默认为1。代表只显示opcode代码,并不是真正执行
下图:没有使用@的opecode的代码
下图:使用@的opecode的代码
优化点:合理使用内存
描述:PHP有内存回收机制,但是也要小心使用内存
建议:unset()及时释放掉不适用的内存(注 unset()出现注销不掉的情况)
情况1:只有当指向该变量的所有变量(如引用变量)都被销毁后,才会释放内存
$s=str_repeat(‘1’,256); //这和第二个例子完全相同
$p=&$s;
$m=memory_get_usage();
unset($s); //销毁$s
unset($p);
$mm=memory_get_usage();
echo $p.’
‘;
echo $m-$mm;
错误的:情况2:unset()函数只能在变量值占用内存空间超过256字节时才会释放内存空间。
<?php<br /> $s = str_repeat('1',255); //产生由255个1组成的字符串<br /> $m = memory_get_usage(); //获取当前占用内存<br /> unset($s);<br /> $mm = memory_get_usage(); //unset()后再查看当前占用内存<br /> echo $m-$mm;<br /> <br /> ?>
解释一下:网上很多说是php5在win下是无法销毁的但是我试验过的5.2版本以及7版本 是可以消除的,代码输出为264
优化点:尽量少的使用正则表达式
描述:正则表达式的回溯开销比较大
建议:利用字符串处理函数,实现相同逻辑
优化点:避免在循环内做运算
描述:循环内的计算式将会被重复计算
例如:
<?php
for($i=0;$i<strlen($str);$i++){
}
优化点:减少计算密集型业务
描述:不适合这个场景,比如大批量日志分析、数据处理
原因:语言特性
适合场景:衔接Webserver与后端服务、UI呈现
优化点:务必使用带引号字符串做键值
描述:PHP会将没有引号的键值当做常量,产生查找常量的开销
代码:
<?php
define(‘key’, ‘val’);
$array=array(
‘key’=>’hollo’,
‘val’=>’word’
);
echo $array[key];//输出word,把key当常量,获取了val
echo $array[‘key’];
?>
PHP周边问题的分析:Linux运行环境、文件存储、数据库、缓存、网络
常见PHP场景的开销次序:
读写内存、读写数据库、读写磁盘、读写网络数据 从小到大,后面三个都是基于文件的形式
访问数据库 和 直接访问磁盘对比的话,如果网络延迟不是很大的话,还是访问数据库快点,因为虽然数据块也是基于磁盘的,但是数据库比如 MySQL会做很多优化来避免读取磁盘以及避免随机磁盘I/O,所以一个高性能数据库肯定是介于使用内存和使用磁盘之间的。如果数据库用得好的话,会比直接读磁盘快。
优化网络请求:
坑:对方接口的不确定因素
网络稳定性
解决: 1.连接超时 200ms
读超时 800ms
写超时 500ms
2.将串行请求并行化
使用curlmulti*()
使用swoole扩展 <br /> 但是使用curl的一个问题是,我们同时发送n个请求,它的返回是依赖最长的耗时连接请求,所以的话如果并行请求中有一个慢了,所有的都慢了
swoole的并行化是通过php的扩展c这个层面多线程的进行并行化请求
压缩PHP接口输出
如何压缩: 使用Gzip
利:利于我们数据输出,Client端能更快获取数据
弊:额外的cpu开销(服务器端的压缩,client端的解压)
缓存重复计算内容:
多次请求内容不变的情况下
流程图:
常用与模板的缓存,例如Smarty开启caching,并且设置cache的目录就开启了
重叠时间窗口思想:实质就是把串行的请求改为并行的,但是只有在后一个任务不强依赖前一个任务的
输出的时候
旁路方案:传统的 x.php->p1->p2->p3->p4
而旁路的是:在执行p2的时候并行的执行P3,这样也是有前提的,后一个任务不依赖前一个
在实际的情况中,我们可能在模板的拼装、渲染路上打造到另外一条路上,因为这个环节没有其他的php运算和接口调用,就是模板根据变量渲染模板,通过HHVM这个引擎来做静态文件的渲染,完成后再回到主流程上
4.PHP性能问题的具体分析
工具:XHPorf(Fackbook的PHP性能分析工具)
5.PHP性能瓶颈解决办法
Opcode Cache :PHP扩展APC、yac
扩展实现:通过PHP扩展代替原PHP代码中高频逻辑
Runtime优化:HHVM