编程学习网 > PHP技术 > php高级 > PHP性能优化
2020
09-28

PHP性能优化



1.什么情况下会碰到PHP性能问题?

  • PHP语法使用的不恰当
  • 使用PHP做了它不擅长的事情
  • 用PHP语言连接的服务不给力
  • php自身的短板
  • 我也不知道的问题

 

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.'<br />';
        echo $m-$mm;

错误的:情况2:unset()函数只能在变量值占用内存空间超过256字节时才会释放内存空间。

 

           <?php
            $s = str_repeat('1',255);   //产生由255个1组成的字符串
            $m = memory_get_usage();    //获取当前占用内存
            unset($s);
            $mm = memory_get_usage();   //unset()后再查看当前占用内存
            echo $m-$mm;
             
            ?>

解释一下:网上很多说是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.将串行请求并行化    

使用curl_multi_*()


使用swoole扩展

但是使用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

扫码二维码 获取免费视频学习资料

Python编程学习

查 看2022高级编程视频教程免费获取