浅谈PHP性能问题(一)

发表于2014-08-29 16:18  |  次阅读  |  0条评论  |   作者:admin

具体PHP的内核和机制问题,应该是09年底到11年那阵子很火,很多人从不同角度各侧面都分享过很多次了,我就不重复造轮子了。12年刚进公司时做了次分享,如果有兴趣可以参考附件的ppt。 本文主要是从这里出发,谈论PHP的性能问题。

1.  Where,PHP怎么工作的,性能瓶颈的背景

先上一张12年时画的关于PHP的流程图。

图1:PHP及其SAPI的工作流程

(1)看图说话

中间实现部分分开上下两部分,上面为上层应用与SAPI,下面为PHP。

右边虚线为PHP的前置启动,一般需要上层应用启动监听相应的web端口,同时PHP-CGI启动,初始化各扩展分配所需的资源,并向ZendEngine注册函数。

左上虚线为关闭时行为

左下为PHP核心与ZendEngine,ZE主要有3大类功能:

A. PHP语言编译:把PHP语言解释为opcode,然后在vm中执行

B. PHP语言功能:比如OO的实现,变常量等数据结构实现,内存管理,接口,闭包和异常管理

C. Zend API:对信号、模块和内置函数、类的管理,接口管理,包括注册、参数解析等

图2:Zend Engine功能

 

(2)上层应用和SAPI

首先PHP是基于请求的,通常实际生产环境中会有上层应用,并提供SAPI来为解耦与兼容不同的上层应用,比如Apache,IIS,CLI等。

上层应用在监听到动态请求,通常通过请求资源的扩展名.php判断,把请求处理转发给PHP-CGI处理。

这样做,可以很好的解耦,保证兼容上层应用。

但,这样也导致了各种问题。

2.  What,PHP性能问题具体是?

其他观点大家肯定也听很多了,我给大家说几个典型的吧:

我记得之前问过鸟哥,答曰各种hashtable检索,比如变量表,常量表,类表等。这从语言本身的实现层面来说没有问题。

以我自己的经验来看,PHP性能瓶颈主要在以下几个方面:

(1)解释型语言的Opcode解析成本问题

一般都是都是用opcode cache。eacc之类的,这个方面产品多,应用广,较成熟不累述。

但是,在语言编译优化上,其实远远不够,比如鸟哥2013年11月分享的Opcache做的14点优化里,都与成熟的C/C++编译器gcc根本没 法比。 相对性能对比而言,eacc ~= opcache > APC。主要原因是eacc在锁机制上实现的更好,spinlocks 相对于 mutex 对多核CPU的利用更有优势。

测试数据 eacc 大约比 APC提升13%

http://2bits.com/articles/benchmarking-apc-vs-eaccelerator-using-drupal.html

而opcache对于APC的提升是7-10%。

但是opcode cache,仅解决了解释成本的问题。

(2)字节码跑在虚拟机上的问题

最终字节码必须跑在虚拟机上,而非直接执行,所以性能上终究有问题。简单的类比就是Java和C/C++的性能区别。

而Facebook的Hiphop(HHVM)把PHP语言转为C++然后再编译执行,它对性能改善近1.8倍,很好的说明了这个性能问题。

目前据我了解,贴吧的百度RD不少人是往这块努力的,LAMP架构和性能优化的项目。

另外,其实HHVM的方案仍然不够彻底,另外有个最理想的方案,正是我目前在努力的方向,具体等出结果再告知。

(3)SAPI的机制问题

这里涉及到respawn机制,就是面向请求的问题

PHP的生命周期是从WebServer启动时spawn一个cgi进程开始的,在主流的worker模式中,在响应若干请求后(MaxRequestsPerChild)会respawn一次。

而每次响应请求时,必须往ZE里初始化资源和注册模块的函数。Minit(M的次数与所调用的扩展个数相同)。

而请求结束后,处理结果是要从PHP传给上层应用,最后执行Mshutdown清理。

这样相比于C/C++的后端服务而言,做了相当多的额外无用功能,这是导致PHP性能低的关键

mod_php和fastcgi目前仍然是这样方式,所以主流PHP的性能瓶颈在这点上,据我所知,百度和腾讯(朋友网除外)目前都是这种方式。

Rasmus在08年的时候引入yahoo的信号延迟处理,为使信号屏蔽机制可用于 SAPI,提高PHP性能。之后,在11年的时候提出一种方案,就是用zeroMQ + libevent作为扩展的方式,用PHP写调用这些扩展的接口去监听指定端口,这样就相当于用PHP进行后端服务处理。在我想来主要是为了解决SAPI 解耦成本的问题,尝试不通过webserver,直接用PHP本身去实现webserver并监听端口请求。

果然,PSF给PHP加上epoll/kqueue做了一套网络编程框架,TCP用Multi-Reactor,UDP借鉴LVS的半同步/半异步模型,性能能达到2-8wGPS的水平,自身用PHP实现了一套web server。

这样就既可以和node.js一样用全异步回调方式处理业务逻辑,也可以实现多进程同步实现自身闭环,而不用再依赖恶心的sapi respawn机制了。以下是PSF的性能测试数据:

并发数量 TCP短 TCP长 UDP 
100         24144 82584 54125
500         33319 80518 49052
1000       30340 66025 44050
2000       26306 37051 38322
5000       13708 16038 -

(4)弱类型导致的内存开销问题

图3:ZVAL的数据建构

ZVAL的数据结构可以看到,为了对弱类型的支持,实际上很大程度增加变量基础结构的内存消耗。导致PHP的内存开销居高不下。具体内存占用实测如下:

 

做过一个简单的对比,一个包含1000个元素的二维数组,其脚本的文本文件大小 133,625字节,加载成PHP数组后,实际占用空间为577368字节,大概在4.27-4.3倍左右。 扣除掉回车,=> 逗号,单引号,大小为51444,倍数为11.22倍。结构类似以下(占用800字节, C语言中这种结构体, 大概占用实际空间29字节):

array(

    760 => array (

    'cid1' => 1,

    'cid2' => 760,

    'cid3' => 0,

    'className' => '海外地区',

    'level' => 2,

    'deleted' => 0,

  ),

   ……

)

800 / 29 = 27.58倍,大约PHP数组对内存的开销比例是C语言结构体的20-30倍。

弱类型本身不是问题,但如果在PHP中要实现自定义数据类型是以zval为基础,所以只能通过扩展开发来实现对内存的精细控制。

(5)弱类型导致的CPU运算开销

由于逻辑处理始终要考虑多种数据类型,中间的运算与计算实现成本较强类型增加很多。如快排实现,单独写了个zend_qsort.c。

(6)Zend Engine的问题

核心本身的问题,也是PHP性能瓶颈的一个关键点,Zeev和Andi的Zend引擎,显然没有达到业界的顶级水平。 比如垃圾回收机制,Java是火车头算法,而PHP的CG没有类似的算法,内存分配是,以块为单位去分配的,但是在回收的时候,只是

(7)PHP圈子不具备成熟的优化生态

我在这个圈子有9年多了,看着很多PHP程序员从起步开始,要不然转架构,要不然转C/C++,转了后鲜少仍做原来的。

或者有很多程序员其实本身就是C语言开发,实际产品需要做的业务开发。

像之前Rasmus带的老yahoo的一些程序员,其实都算是C/C++程序员,那么成为PHP语言本身的开发者相对容易。但他们其实是C语言开发者,而PHP语言对他们而言则相当于是一款产品。

这样就很难有靠PHP语言入门的程序员,能够用成长后的产出对PHP生态圈产生大贡献。

主要原因也是因为PHP仍在前端或业务端打转,涉及到优化时,C/C++语言程序员会拥有更大更扎实的知识积累与逻辑熟悉度。

Tobe continued: 3.  How,PHP性能如何优化?

引用:

惠新宸(2013) 一个关于Zend O+的小分享, 详见http://www.laruence.com/2013/11/11/2928.html

Rasmus Ledorf(2008) Zend Signal Handling, 详见:https://wiki.php.net/rfc/zendsignals

赵海平 (2012) The HipHop compiler for PHP, 详见:http://dl.acm.org/citation.cfm?id=2384658

https://github.com/facebook/hhvm/

韩天峰(2012) 朋友网PHP高性能Server框架PSF介绍,  http://km.oa.com/articles/show/133541

Michiaki Tatsubori,Akihiko Tozawa,Toyotaro Suzumura,Scott Trent,Tamiya Onodera (2010) Evaluation of a just-in-time compiler retrofitted for PHP,
详见: http://dl.acm.org/citation.cfm?id=1736015

本站关键字:sunny90 web开发 数据库 移动开发 服务器 Nginx Mysql PHP
Copyright © sunny90版权所有 power by sunny90.com  
湘ICP备14012284号-1,粤公网安备 44030602000307号