宏观层面,也就是对 PHP 语言本身的性能分析又分为三个方面:
一、PHP 作为解释性语言的性能分析与提升
如上所示,从上图可以看到,每一次运行,都需要经历三个解析、编译、运行三个过程。
相对每一次解析、编译,读到脚本之后,直接从缓存读取字节码的效率会有大幅度的提升,提升幅度到底有多大呢?
我们来做一个没有 Opcode 缓存的实验。20 个并发,总共 10000 次请求没有经过 opcode 缓存的请求,,得到如下结果:
图3. 没有使用Opcode缓存的请求,20个并发,10000次
这里分别启用 APC 和 Zend OPCache 做实验。启用 APC 的版本。
可以看到,速度有了较大幅度的提升,原来每个请求 110ms,每秒处理请求 182 个,启用了 APC 之后 68ms,每秒处理请求 294 个,提升速度将近 40%。
在启用了 Zend Opcache 的版本中,得到同 APC 大致相当的结果。每秒处理请求 291 个,每请求耗时 68.5ms。
从上面的这个实验可以看到,所用的测试页面,有 40ms 以上的时间花在了语法解析和编译这两项上。通过将这两个操作缓存,可以将这个处理过程的速度大大提升。
二、PHP 作为动态类型语言的性能分析与改进
-
<?php
-
$a = 10.11;
-
$b = "30";
-
var_dump($a+$b);
-
var_dump("10"+$b);
-
var_dump(10+"20");
-
var_dump("10"+"20");
这是一段 Swift 代码,字典只有 14 个键值对,这段代码的编译,9 分钟了还没有编译完成(5G 内存,2.4GHz CPU),编译环境为 Swift 1.2,Xcode 6.4。
也就是加上了类型限定,避免了 planeLocation 的类型推断。编译过程花了 2S 。
首先是用纯 PHP 写成的算法,计算 1000 万以内的素数个数,耗时在 33s 上下,实验了三次,得到的结果基本相同。
可以想见,静态和编译类型的语言,其效率得到了惊人的提升。本程序的 C 语言代码如下:
-
PHP_FUNCTION(get_prime_numbers)
-
{
-
long value;
-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) == FAILURE) {
-
return;
-
}
-
int *numbers = (int *)malloc(sizeof(int)*128*10000);
-
memset(numbers, 0x0, 128*10000);
-
int num = 2;
-
numbers[0] = 2;
-
numbers[1] = 3;
-
bool flag = true;
-
double f = 0;
-
int i = 0;
-
int j = 0;
-
for(i=5; i<=value; i+=2)
-
{
-
flag = true;
-
f = sqrt(i);
-
for(j=0; j<num;j++)
-
{
-
if(i%numbers[j]==0)
-
{
-
flag = false;
-
break;
-
}
-
if(numbers[j]>f)
-
{
-
break;
-
}
-
}
-
if(flag)
-
{
-
numbers[num] = i;
-
num++;
-
}
-
}
-
free(numbers);
-
RETURN_LONG(num);
-
}
三、PHP 语言本身底层性能引擎提升
PHP 5.3 的版本在上面的例子中已讲过,需要 33s 左右的时间,我们现在来看别的PHP版本。分别运行如下:
PHP 5.4 版,相较 5.3 版已经有一定程度的提升。快 6 秒左右。
PHP 5.5 版在 PHP 5.4的基础上又进了一步,快了 6S。
PHP 7 果真是效率提升惊人,是 PHP5.3 的 3 倍以上。
以上是求素数脚本在各个 PHP 版本之间的运行速度区别,尽管只测试了这一个程序,也不是特别的严谨,但是这是在同一台机器上,而且编译 configure 参数也基本一样,还是有一定可比性的。
这样程序性能的效率得到了提升。以上就是有关 PHP 宏观层面的性能优化的分析,在本文的第二部分我们将探讨应用方面的 PHP 优化准则。敬请期待!