阅读这篇文章,可以理解从 PHP 5 到 7(包括 7.1)的性能提升,同时也将理解到即将加入到 PHP 8 的试验性的 JIT 分支版本的性能。

简介

本文将根据韶光作出更新,增加更多信息和基准测试结果,包括尚未发布的新版本,以便更好地理解多年来 PHP 性能演化。
如果您有更正或建议改进,请在文后留言。

php58从PHP 5到PHP 7机能全评测含未宣布的JIT版PHP 8比较 Bootstrap

自 1994 年 Rasmus Lerdorf 创建 PHP 以来, PHP 措辞经历了激烈的演进。
虽然初版是一个大略的一人开拓的 CGI 程序,Rasmus Lerdorf、Andi Gutmans 和 Zeev Suraski 加入了该措辞的第三个版本的开拓,并根本性重新设计。
从那之后, PHP 开拓组也创建并发展起来。

随着项目的发展,由于 PHP 3 天然的可扩展性, PHP 在核心和附加扩展开拓的功能得到了发达发展,如网络通信,解析,缓存和数据库支持。

措辞本身也在发展,带来了一系列的改进。
这包括支持面向工具的构造,例如类,接口, traits,闭包等。

对付许多开拓职员来说,仅有新功能是不足的。
随着措辞越来越受欢迎, PHP 社区对付供应更好性能,可扩展性和更少内存利用的需求越来越强烈。

PHP 开拓团队近 20 年来一贯致力于办理这些需求,虽然 PHP 3 的引入大大提高了性能,但直到 Andi Gutmans 和 Zeev Suraski 引入 Zend Engine 并发布 PHP 4, PHP 的性能才开始变得正式起来。

2000 年推出的新的内存编译器和实行器模型大大提高了 PHP 的性能(提高了 5 倍乃至 10 倍),并首次被正式的 Web 运用程序和站点所利用。
我们可以说,本日 PHP 的成果远远超出了任何人在 PHP 项目出身时的期望。

PHP 的发达发展增加了改进性能的希望。
幸运的是, Zend Engine 中设计的模型为持续优化性能供应了良好的根本。

虽然 PHP 5.0 没有带来本色性的性能提升,并且在某些情形下乃至比 PHP4 更慢,一个由 Dmitry Stogov 领导的团队在社区的大力帮助下已经在后续版本中不断优化措辞,在 PHP 5.6 发布的时候,在大多数情形下,性能提升在 1.5x 和 3x 之间。

2015 年 12 月, PHP 7.0 取得了重大打破。
2016 年 12 月,7.1 版本也带来了一系列增强功能。

PHP 8 性能展望

这是一个出息光明的版本,目前正在开拓当中,由 Zend 的 Dmitry Stogov 主导。
虽然它是基于 PHP 7.1 版本根本,但实际版本号尚未定义,以是本文称这个版本为“试验 JIT”分支下。

关键功能 JIT( :Just-In-Time)编译,是一种将代码转换为另一种字节码(比如运行它的机器 CPU 确当地代码)的技能。
JIT 可以使程序运行更快。

本文涵盖了几个基准测试的结果,从 PHP 5 的第一个版本到 PHP 的试验性 JIT 分支版本,PHP 5 之前的版本性能本文不作先容。

在写这篇文章的时候,我们很难确定 PHP 8 之前是否会有另一个紧张版本,比如 PHP 7.2。
但是可以假设在 PHP 8 发布时,它已经包括当前试验版 JIT 分支的强大功能。

PHP 性能评估

本文只运行纯 CPU 任务脚本的基准测试(不须要I / O操作的任务例如访问文件,网络或数据库连接)。

利用的基准测试脚本如下所示:

bench.php[1] 可在PHP源代码的 php-src/Zend 目录

micro_bench.php[2] 也可以在 PHP 源代码发布的 php-src/Zend 目录中找到

mandelbrot.php[3]

基准脚本仅利用每个PHP紧张版本的最新小版本运行。
因此,测试的版本如下:

5.0.5

5.1.6

5.2.17

5.3.29

5.4.45

5.5.38

5.6.28

7.0.13

7.1.0

开拓版 JIT 分支

当然,我想确定,我们在相同的基准上运行所有小版本,例如在 5.3.0 到 5.3.29 之间。
结果是有说服力的:性能方面的紧张增强不是由小版本带来的,而是紧张版本号的变革,例如从 PHP 5.4 到 PHP 5.5,或从PHP 5.6 到 PHP 7。

小版本没有显示任何明显的性能改进。
这意味着相同的脚本该当以相同的速率运行,无论您利用 PHP 5.4.0 还是 PHP 5.4.45。

您可以查看基准进程部分,详细解释主机系统的设置,各个基准的运行办法以及如何阐明时序结果。

纯 CPU 基准测试结果

这部分给出了每个 PHP 版本的基准测试结果。

每个基准列显示 3 个值:

韶光:实行韶光,以秒和毫秒为单位

%rel。
gain:相对付以前的版本收益的实行韶光。
不才面的表格中,例如,%rel。
bench.php 和版本 5.3.29 的收益是 31.89%,意味着该脚本比 5.2.17 版本运行快 31.89%。

abs。
gain:与 PHP 5.0 比较脚本运行的收益。
如果你看看bench.php 和试验性的 JIT 分支的这个列的交集,你会把稳到,对付这个特定的测试基准,PHP 8 比 PHP 5.0 快 41 倍以上。

纯CPU基准测试的结果如下所示:

测试不能在 5.3 之前的版本上运行,由于它利用了尚未实现的工具功能。

此列中的结果有点偏颇,由于基准须要至少 PHP 5.3 运行。
把它们当成纯粹解释,由于他们不能与 PHP 5.0 性能进行比较。

这是一个 mandelbrot.php 脚本的修正版本,它运行得太快,在 7.1.0 和试验 JIT 分支无法准确的统计韶光,我们在脚本中运行打算 100 次而不是 1 次。

当然,这些都是纯 CPU 的基准测试。
它们不涵盖 PHP 性能的所有方面,它们可能不代表真实情形。
但是结果足够显著,足以解释几个方面的问题:

PHP 5.1 将 PHP 5.0的 性能提高了一倍多

5.2 和 5.3 带来了他们自己的一些性能增强,但他们没有像5.1版本那样引人瞩目。

5.4 版本是一个大的性能改进。
(PHP核心开拓者鸟哥曾经ppt解释php5.4性能改进的缘故原由[4])

opcache 扩展插件与 5.5 和 5.6 版捆绑在一起。
当相同的脚本在 Web 做事器连续运行时,由于更快的代码加载会带来性能增强。
但是,opcache 不会真正显示其在CLI模式下实行脚本的上风。

PHP 7.0 是性能方面的一个重大打破。
Zend Engine 已经完备重新设计,我们可以在这里看到这项事情的结果。
(这里有PHP核心开拓者鸟哥的ppt解释php 7性能改进的缘故原由[5])

PHP 7.1 在 opcache 扩展中引入了 opcode 优化。
这再次阐明了上述表格中当与 7.0 比较时,性能的增益。

试验 JIT 分支是另一个重大打破,JIT 可以对现有代码供应很大的性能改进,但在某些情形下,你可能会把稳到速率提高只有几个百分点,在最坏的情形下,它乃至可能会变慢,由于编译不会天生更快的代码。
请记住,此功能目前正在开拓中。

本节先容了 3 个纯 CPU 基准测试脚本的结果。
在运行常日实行的以数据库或文件访问范例场景的 PHP 运用程序时,它不会给出同样的数字,但我认为他们能够代表您对代码的某些部分期望的性能改进。

PHP 每个版本的性能提升

PHP 5 比较 PHP 4 带来了明显的改进。
Zend Engine 是 PHP 阐明器的核心,它已经完备重新设计( Zend Engine 2),为将来的增强功能奠定了根本。
本文不多先容 PHP 4 和 PHP 5 之间的差异,只简要概述的 PHP 5.0 之后发生了什么。

以下部分列出了在后续 PHP 版本中的改进。
请把稳,这里仅列出影响 PHP 核心的修正。
有关更完全的描述,请查看 PHP 5 和 PHP 7 的change log。

PHP 5.1

Compiled variables

Specialized executor

Real-path cache

Faster switch statement handling

Faster array functions

Faster variable fetches

Faster magic method invocations

PHP 5.2

New memory manager

Optimized array/HashTable copying

Optimized require_once and include_once statements

Small optimization on specific internal functions

Improved compilation of HEREDOCS and compilation of interpolated strings

PHP 5.3

Segmented VM stack

Stackless VM

Compile-time constants substitution

Lazy symbol table initialization

Real-path cache improvement

Improved PHP runtime speed and memory usage

Faster language parsing

Improved PHP binary size and code startup

PHP 5.4

Delayed HashTable allocation

Constant tables

Run-Time binding caches

Interned Strings

Improved the output layer

Improved ternary operator performance when using arrays

PHP 5.5

Improved VM calling convention

OPcache integration

Other misc. optimizations to the Zend Engine

PHP 5.6

Optimized empty string handling, minimizing the need to allocate new empty values

PHP 7.0

下面大部分列出的改进都与 Zend Engine 干系:

Core data structures re-factoring

Better VM calling convention

New parameters parsing API

Yet another new memory manager

Many improvements in VM executor

Significantly reduced memory usage

Improved __call and __callStatic functions

Improved string concatenation

Improved character searching in strings

PHP 7.1

New SSA based optimization framework (embedded into opcache)

Global optimization of PHP bytecode based on type inference

Highly specialized VM opcode handlers

PHP 8 / 下一代试验性 JIT 分支版

Just-In-Time compiling

性能如何衡量

基准化比纯挚运行 Unix 韶光命令来丈量脚本的实行有所差异。
这便是为什么我经历了以下步骤:

配置系统

首先我设置了一个具有以下特性的专用系统:

一个带有1个2.4GHz虚拟内核,2GB RAM和两个SSD驱动器的VPS,一个用于存储操作系统数据,另一个用于存储各种PHPyuan dai ma,二进制文件和报告输出

Debian Wheezy操作系统,版本3.2.82-1

Gnu C编译器版本4.9.2-10(Debian Jessie发行版)

虽然系统捆绑了Gnu C编译器版本4.7.2,但须要升级到更新的版本。
试验性 JIT 分支必须用Gnu C> = 4.8编译。

编译源代码

在构建完全发行版之前,利用以下选项运行配置脚本:

--prefix=/usr/local/php --disable-debug--disable-phpdbg--enable-mysqlnd--enable-bcmath--with-bz2=/usr--enable-calendar--with-curl--enable-exif--enable-fpm--with-freetype-dir--enable-ftp--with-gd--enable-gd-jis-conv--enable-gd-native-ttf--with-gettext=/usr--with-gmp--with-iconv--enable-intl--with-jpeg-dir--enable-mbstring--with-mcrypt--with-openssl--enable-pcntl--with-pdo-mysql=mysqlnd--with-png-dir--with-recode=/usr--enable-shmop--enable-soap--enable-sockets--enable-sysvmsg--enable-sysvsem--enable-sysvshm--enable-wddx--with-xmlrpc--with-xsl--with-zlib=/usr--enable-zip--with-mysqli=mysqlnd

把稳,在编译旧版时,上面的一些选项须要被禁用或被其他替代,并且并不是所有的扩展都可用或可以被编译。

运行基准测试

每个基准测试都利用 PHP CLI 专用脚本运行,该脚本遵照以下步骤:

利用 microtime函数从内部获取脚本实行韶光。
在此修正后,基准脚本将如下所示:

<?php$__start__ = microtime( true );/original benchmark script code here/fprintf( STDERR, microtime( true ) - $__start__);?>

实行 2 次运行,以确保 PHP 可实行文件和基准测试脚本内容都在操作系统缓存中

运行脚本 5 次,并提取最小,最大和均匀运行韶光,如脚本报告。
本文仅显示均匀运行韶光,称之为“脚本运行韶光”。

php.ini 文件如下所示:

engine = Onshort_open_tag = Offrealpath_cache_size = 2Mmax_execution_time = 86400memory_limit = 1024Merror_reporting = 0display_errors = 0display_startup_errors = 0log_errors = 0default_charset = \"大众UTF-8\"大众[opcache]zend_extension=opcache.soopcache.enable=1opcache.enable_cli=1opcache.optimization_level=-1opcache.fast_shutdown=1opcache.validate_timestamps=1opcache.revalidate_freq=60opcache.use_cwd=1opcache.max_accelerated_files=100000opcache.max_wasted_percentage=5opcache.memory_consumption=128opcache.consistency_checks=0opcache.huge_code_pages=1// PHP 8/Next onlyopcache.jit=35opcache.jit_buffer_size=32M

剖析运行结果

利用 Unix time 命令来计时,输出如下所示:

$ time php bench.phpreal: 0m1.96suser: 0m1.912ssys: 0m0.044s

第一个值,real :, 是命令开始到终止之间的韶光(当你回到 shell 提示符)。

第二个值,user :,解释在用户模式中花费的韶光(在我们的例子中,这是在 php 可实行文件中花费的韶光)。

末了一个值 sys :,解释在操作系统(内核)调用中花费的韶光。
这个值该当是最小的,但是如果你的代码访问缓慢的设备结果会比较大。
重负载的操作系统也可能影响此处报告的值。

在空闲系统上常日,数量(user + sys)该当非常靠近 real。
这是在上面的例子中的情形:user + sys = 1.956s,real 是 1.960s。
0.004s 的差异不属于当提高程:它仅仅意味着操作系统实行任务所花费的额外韶光,例如调度。

同一个脚本在一个负载很重的系统上实行,并行编译 3 个不同的 PHP 版本:

$ time php bench.phpreal: 0m7.812suser: 0m2.02ssys: 0m0.101s

在这里我清楚地看到,系统本身的重负载对利用的韶光(大概在系统韶光)有重大影响。

这便是为什么我在这个基准中保留一个额外的值,操作系统开销,这是调用的韶光和(用户+系统)韶光之间的差。

在纯 CPU 基准测试活动期间,我确保在 99% 以上的韶光,这个值严格小于 100 毫秒,纵然运行须要几十秒钟完成的脚本。

特殊鸣谢

特殊鸣谢 Dmitry Stogov 和所有 PHP 核心开拓者们。

本文是和 Dmitry Stogov 互助完成的 , 他帮助审阅了文章内容 , 来担保这个文章的精确性。

Dmitry Stogov 曾经是 Truck MMCache 的开拓者,在 PHP4 时期就可以用作共享内存中缓存 PHP Opcode,从那时候起,Dmitry Stogov 就加入了 Zend,一贯到现在。

Dmitry 是 PHP NG 的紧张开拓者 , 也便是我们后来知道的 PHP7, 和 Dmitry 一起互助的有 Xinchen Hui(鸟哥),Nikita Popov,正是他们在一起开拓了 PHP7 以及后来的版本包括 PHP JIT。

在 PHP7 之前 , PHP5 时期的 Andi Gumans, Zeev Suraski 以及 Stas Malishev 等也做了很多的事情来提升 PHP5 的性能,限于篇幅,本文就不详细先容。

结论

本文的目的是给你一个不同版本PHP性能的概述,从 5.0 开始,到当前正在开拓的最新版本,利用一组已知的基准脚本。

它还为您供应了由每个连续 PHP 版本办理的性能改进方面的列表。

本文将随着新的 PHP 版本的公布而更新,并且将来会添加新的基准测试结果。
我也希望添加一些真实天下的 PHP 运用程序,如 WordPress 的基准测试结果。

如果您有任何问题或创造不准确,请随时揭橥评论。
同时,与其他对 PHP 性能感兴趣的开拓职员分享这篇文章。

本文中文版由高可用架构志愿者翻译,英文原文地址[6]。

先容一个跟编程措辞密切干系的一个技能活动,GIAC 环球互联网架构大会将在 12 月 16 ~ 17 日在北京举行,PHP7 核心开拓者,链家网技能副总裁惠新宸(鸟哥)作为本次大会联席主席。

架构师最主要的是理解干事的方法和方向,通过 GIAC 两天 40 个案例,可以理解互联网架组成长的最新的动态,提升自己的架构视野。

参加 GIAC,全面理解最新互联网架构知识,末了 3 天购票机会,识别二维码或点击阅读原文进入购买页面。