php性能的问题

一.影响php性能的常见原因

1.php自身语法使用不当

2.php做了不擅长的时期()

3.php的周边环境(服务器Linux,磁盘:文件存储,数据库,缓存:内存,网络:带宽)

4.php自身的短板

5.未知问题

二、分析

PHP代码运行流程 
*.php(PHP文件)->Scanner(扫描代码,分析)->Exprs(保存成zend引擎可以识别的文件)->Parser(解析)->Opcodes(能被执行的文件)->Exec(执行)->Output(输出结果)

 

1.php语言级的性能优化。指的是PHP语法基本功能,这部分优化比较简单易见、快速可行,比较快速看到效果。

1.1  少写PHP的代码,多用PHP自身能力解决问题

性能问题

自写代码冗余较多,可读性不佳,并且性能低,如代码很长很长...PHP代码越长PHP的执行效率越慢。

     为什么性能低?

PHP代码需要解析编译为C语言,底层C语言又要编译成汇编语言机器语言才能执行,这个过程在每次请求过来之后都要处理一遍,所以开销很大(项目变大的话...)。

     解决方法:

多使用PHP内置的变量、常量、函数。我们用PHP代码实现的功能和使用PHP内置的函数实现的同样功能差别是有的。

 1.2 PHP内置函数的性能优劣。

情况描述
PHP内置函数之间依然存在快慢差别;少用PHP魔术方法;

     建议:
     多去了解PHP内置函数的执行实现复杂度。
     测试方法:比较效率测试,如用microtime()函数,取差值,精确到毫秒级别;Linux的time命令可以查看开销。

 

1.3 产生额外开销的错误抑制符号“@”,最好别用(不管是性能优化和项目的健壮性等方面)。

    @的逻辑是在代码前和代码结束后增加了Opcode,Opcode的作用就是忽略报错,其实就是相当于增加了error_reporting设置,等级报错为忽略(vld扩展可以查看被隐藏的Opcode)

1.4 合理使用内存

    利用unset()及时释放不使用的内存,比如一些数据库多余字段(注意:unset()有时会出现注销不掉的情况)

    当出现变量引用是,需要把两个变量都unset才可以注销内存;或者直接$变量=null来注销

1.5 尽量少用正则表达式

    正则表达式的开销大,使用起来简单,但是性能低因为,正则表达式需要回溯;正则表达式越长,回溯的开销越大,优化正则表达式是需要技术水平的,正则技术不达标,不要乱用正则。

1.6 避免在循环内做运算。

    循环内的计算式将被重复计算(我们在for循环或者while循环,会有重复计算,影响性能问题)

1.7 减少计算密集型业务

情况描述:

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呈现,也就是配合模板引擎做模板输出,其实就是一些字符串文本处理。

 

1.8 务必使用带引号字符串做键值(数组的Key字段)。

    PHP会将没有使用引号的键值当做常量,产生查找常量的开销,如果查找到了常量有这个字符串,那么就把常量作为这个值了。

    建议:严格使用引号作为键值,单引号即可。

1.9 尽量静态化

   一个方法能被静态,就声明它为静态的,速度可以提高1/4,

其实静态方法和非静态方法的效率主要区别在内存:
静态方法在程序开始时生成内存,实例方法在程序运行中生成内存,所以静态方法可以直接调用,实例方法要先成生实例,通过实例调用方法,静态速度很快,但是多了会占内存
任何语言都是对内存和磁盘的操作,至于是否面向对象,只是软件层的问题,底层都是一样的,只是实现方法不同。静态内存是连续的,因为是在程序开始时就生成了,而实例申请的是离散的空间,所以当然没有静态方法快。 静态方法始终调用同一块内存,其缺点就是不能自动进行销毁,而是实例化可以销毁。

 

 1.10   用单引号代替双引号来包含字符串,这样做会更快一些。因为 PHP 会在双引号包围的 字符串中搜寻变量,单引号则不会

1.11  echo 比 print 快,并且使用 echo 的多重参数(译注:指用逗号而不是句点)代替字符串 连接

1.12 include 文件时尽量使用绝对路径,因为它避免了 PHP 去 include_path 里查找文件的速 度,解析操作系统路径所需的时间会更少

1.13  include()与require()的区别及require_once的代价

include() 遇到文件处理失败时,会产生一个警告;

而require()则会显示一个致命错误。也就是说在脚本执行过程中,如果代码中有错误,include()则会忽略错误并继续执行脚本,而require()则会停止脚本运行。 在php中使用require_once
/include_once虽然方便,但是代价昂贵,据测试数据来看,require_once比require慢3-4倍,所以在php开发中,我们应该尽量使用require/include。

 

1.14 foreach 效率更高,尽量用 foreach 代替 while 和 for 循环;

总体来说,如果数据库过几十万了,才能看出来快一点还是慢一点,如果低于10万的循环,就不用测试了。php推荐用foreach。
循环数字数组时,for需要事先count($arr)计算数组长度,需要引入自增变量$i,每次循环都要进行条件判断$i<$c,然后自增$i++,输出数组元素时,$arr[$i]需要进行哈希操作.

而foreach循环数组时,指针会自动指向下一个元素,不需要计算数组长度,没有条件判断和自增变量,调用元素时也没有哈希操作,所以性能肯定要比for和while高.另外,for和while对存在键值映射的关联数组无能为力.
所以,遍历数组,首选foreach.foreach也是我PHP里最喜欢的关键字,因为它确实强大.array_map
/array_filter/array_walk遍历数组的方式和foreach一样,但需要执行回调函数,所以也比foreach慢.

2.php周边环境的性能优化

性能排列:内存>数据库>磁盘>网络

2.1 减少文件的操作,操作完成要关闭文件。

2.2 

网络优化:

  网络原因:

   1.对方接口不确定。接口地址错误;数据错误

    2.网络不稳定

   网络优化:

  a.设置超时时间

   1.链接超时 200ms

   2.读超时  800ms

   3.写超时 500ms

  b.将串行请求并行化;把多次请求,放到一次请求中

    1.使用curl_multi_*()

     2.使用swoole扩展

2.3 压缩php接口

   使用: Gzip ,php有对应压缩和解压的函数

   利:利于我们的数据的数据输出,Client端能更快获取数据

   弊:额外的cpu开销

2.4 缓存

 对于变化少,访问量大的数据做缓存;缓存可以减轻服务器负载、减低网络阻塞、增强www可扩展性

  a.文件缓存

  b.memcached

  c.Redis

2.5 旁路方案

 

3.php性能的测试

3.1 使用内置函数,测试代码执行时间;microtime()

3.2 Linux的time命令

3.3 apache测试工具,ab 可以测试并发时执行代码所需要的时间。

posted @ 2017-10-21 15:22  myvic  阅读(1928)  评论(0编辑  收藏  举报