原文链接: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扩展主要的两个参数列表

    1. -dvld.active 默认为0。代表是否在运行PHP文件是激活vld扩展,
    2. -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字节时才会释放内存空间。

    1. <?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 /> ?>
    2. 解释一下:网上很多说是php5在win下是无法销毁的但是我试验过的5.2版本以及7版本 是可以消除的,代码输出为264

    优化点:尽量少的使用正则表达式
    描述:正则表达式的回溯开销比较大
    建议:利用字符串处理函数,实现相同逻辑

    优化点:避免在循环内做运算
    描述:循环内的计算式将会被重复计算
    例如:
    <?php
    for($i=0;$i<strlen($str);$i++){

    1. }

    优化点:减少计算密集型业务
    描述:不适合这个场景,比如大批量日志分析、数据处理
    原因:语言特性
    适合场景:衔接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*()

    1. 使用swoole扩展 <br /> 但是使用curl的一个问题是,我们同时发送n个请求,它的返回是依赖最长的耗时连接请求,所以的话如果并行请求中有一个慢了,所有的都慢了
    2. swoole的并行化是通过php的扩展c这个层面多线程的进行并行化请求

    压缩PHP接口输出
    如何压缩: 使用Gzip
    利:利于我们数据输出,Client端能更快获取数据
    弊:额外的cpu开销(服务器端的压缩,client端的解压)

    缓存重复计算内容:
    多次请求内容不变的情况下
    流程图:

    常用与模板的缓存,例如Smarty开启caching,并且设置cache的目录就开启了

    重叠时间窗口思想:实质就是把串行的请求改为并行的,但是只有在后一个任务不强依赖前一个任务的
    输出的时候
    旁路方案:传统的 x.php->p1->p2->p3->p4
    而旁路的是:在执行p2的时候并行的执行P3,这样也是有前提的,后一个任务不依赖前一个

    1. 在实际的情况中,我们可能在模板的拼装、渲染路上打造到另外一条路上,因为这个环节没有其他的php运算和接口调用,就是模板根据变量渲染模板,通过HHVM这个引擎来做静态文件的渲染,完成后再回到主流程上

    4.PHP性能问题的具体分析
    工具:XHPorf(Fackbook的PHP性能分析工具)

    5.PHP性能瓶颈解决办法
    Opcode Cache :PHP扩展APC、yac
    扩展实现:通过PHP扩展代替原PHP代码中高频逻辑
    Runtime优化:HHVM