PHP是一种执行起来非常迅速的编程语言,但是比起仅仅优化代码来说仍然值得优化PHP本身。
本文我们将根据一些实效阐述为什么优化PHP本身要比优化代码来的更贴切,以及为什么需要理解根据PHP在你的服务器上其他相关子系统的表现找出瓶颈并修复之。与此同时,我们也提到了如何优化您的PHP代码来让他们拥有更快的执行速度。
获得高性能
当我们谈及好的性能,往往不仅仅是指您的PHP代码执行起来有多快。性能是一套在可量化评测和速度之间取出的平衡。仅仅依靠使用更少资源的代码执行起来也许比在高速缓存中之行的代码更慢,并且相同的一组(在高速缓冲中执行的)代码可以在同时并发执行在一台Web服务器上。
在下面的例子中,A.php算作一位尽可能跑得快的赛跑选手,而B.php是一个几乎可以以同一慢速永远跑下去的马拉松选手。轻负荷情况下,A.php可以充分的快,但是当流量增加后,B.php的性能表现将仅仅降低一点点而A.php会垮掉。
让我们来通过一个事实来验证此说法更深远的本质意义。假设我们需要读取一个250K的文件并生成一个关于此文件的HTML概要。我们写了两个脚本来做同样一件事:hare.php将一次性读取整个文件到内存中,然后一步执行到位;而tortoise.php每次只读取文件的一行,并且决不超过内容容量。结果Tortoise.php因为多次读写需要更多的系统回应而慢得多。"
程序每执行一次,hare.php需要0.04秒CPU执行时间和10Mb的内存,而tortoise.php需要0.06秒CPU执行时间和5Mb的内存。服务器共有100Mb实际内存容量并且其CPU有99%是空闲的。我们同时假定执行这样一个简单事件不产生内存碎片。
当有10各程序并发执行时,hare.php将发生内存溢出(10 ×10 = 100)。与此同时,tortoise.php仍将有50Mb空余内存可用!11个程序并发执行将使hare.php彻底“溃败”因为它开始需要使用虚拟内存——执行速度有可能降低到其常规速度的一半以下;而且现在每一个单独程序进程需要0.08秒CPU执行时间。而此期间,tortoise.php仍旧运行在其常规CPU执行时间——0.06秒!
以下表格中,执行得更快的PHP脚本使用粗体区分开来:
如您在上例中看到的,获得更好的性能不再仅仅是写出执行起来更快的PHP程序。高性能PHP表现需要对底层硬件知识以及操作系统、软件支持如Web服务器、数据库等有一个良好认识和理解。
瓶颈
以上两个例子让我们看到了(性能)下降的瓶颈所在。当拥有无限大容量的内存时,hare.php的确是始终比tortoise.php快。但是,仅仅认为内存是PHP整体性能的瓶颈所在显得过于单纯——实际上远不止这些:
(a) 网络
你的网络有可能是***的瓶颈所在。如果你有10M的带宽——最多你只能获得1M/秒的传输速度。如果假设每个PHP页为30k,那么每秒仅仅只传输33页就将使你的网络带宽达到饱和。更多导致瓶颈产生的因素包括频繁访问低速DNS,或者网络设备仅能获得十分有限的存储。
(b) CPU
如果你监视一下你的CPU负荷情况,发送一个纯静态HTML页面并不会增加CPU负担——就像我们以上提到的,此时瓶颈在于网络。当然啦,对于由PHP生成的复杂动态页面,你的CPU速度自然将成为限制因素之一。拥有包含多个CPU的服务器或者一个服务器阵列将减轻因CPU带来的影响。
(c) 共享存储
共享存储主要在通讯进程中发挥作用,或者是用于储存公共资源(比如多个CPU间的缓存数据或代码)。如果共享存储分配不足,同样将导致瓶颈的发生。
(d) 文件系统
访问硬盘的速度至少比直接读取内存要慢50到100倍。使用高速缓存将使情况有所好转。然而低内存空间将适用于文件缓冲的内存(通常称为虚拟内存)空间减少,进而导致整体性能下降。虚拟内存容易产生大量文件碎片,导致访问硬盘速度下降。在Unix系统上使用大量链接标记同样也会石访问硬盘的速度下降。缺省Linux安装模式下的默认硬盘访问设置也是很不被看好的,因为它是为了兼容性而不是速度。必要时请使用hdparm命令来更改Linux硬盘配置。
(e) 进程管理
在某些操作系统上(比如说Windows系统)创建一个新的进程是很缓慢的操作。这意味着在这些操作系统上作涉及到进程创建的CGI应用会慢许多。这种时候在多进程模式下运行PHP将会有所改善。(注意:老版本PHP尚不支持多进程模式)
应避免你的服务器产生过多的无效进程。举个例子,如果你的服务器是纯Web服务,需关闭(设置是不安装)X-Windows窗口系统。Windows系统上,应禁用微软快速搜索(Office的一部分)和第三方屏保程序(通常会需要100%的CPU利用)。
有些程序你可以考虑删除包括一些不常用的网络协议、邮件服务、病毒扫描、(鼠标,红外线端口)驱动程序等。Unix系统上,假定你通过SSH访问你的服务器,那么你可以考虑去除:
telnetd,inetd,atd,ftpd,lpd,sambad模块
用于收取邮件的sendmail模块
NFS的映射表
xfs,fvwm,xinit,X
你也可以通过修改启动脚本(其路径通常位于/etc/init* 或 /etc/rc*/init*)来实现禁用不同的启动程序。
也可以检查一下定期处理任务安排是否合理,看是否可以在服务器空闲期执行。
(f) 连接到其他服务器
如果你的服务器需要其他服务器提供的服务,此时有可能是其他服务器产生了瓶颈。最常见的就是一个很慢的执行诸多复杂查询的数据库服务器服务于很多其他服务器。
【编辑推荐】