性能测试
测试均基于以下配置进行:
- AMD EPYC 9754 128-Core Processor (腾讯云标准型SA5) / 2C2G
- Linux 6.6.47-12.tl4.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Sep 25 22:06:14 CST 2024 x86_64 GNU/Linux
- 测试日期:2025/02/03
表格的单位均为秒。
总结
性能损失
- 启动虚拟机本身开销较大(初始化环境需要约0.002秒),这也直接导致递归性能损耗明显。
- 大函数(mandel/ackermann)、复杂循环(nestedloop)损耗明显。
- 其他操作性能损失较小。
PHP 8.4 JIT vs 非JIT
- 整体性能提升约5-15%
- 在CPU密集型操作(如mandel、ackermann)上提升更明显
- 简单操作(如ary、hash)提升不明显
PHP 8.4 vs PHP 7.4
- 总体性能提升约10-20%
- 函数调用效率提高
- 字符串操作提升不明显
PHP 7.4 vs PHP 5.6
- 性能差距巨大,7.4通常快3-5倍
- 函数调用速度(快约3倍)
- 数组操作(快约4倍)
- 数学计算(快约4-5倍)
- 所有测试场景都有明显提升
PHP 8.4 + JIT
- docker run --rm -it php:8.4-apache /bin/bash
- php -dopcache.enable_cli=1 -dopcache.enable=1 -dopcache.jit_buffer_size=100M
- PHP 8.4.3 (cli) (built: Jan 17 2025 17:31:49) (NTS)
- PHP 5.2测试需要额外增加命令行参数
-dmemory_limit=1000M
标识 |
未加密 |
推荐 |
PHP 5.2 |
最大保护 |
最大性能 |
simple |
0.006 |
3.745 |
3.719 |
3.466 |
1.748 |
encrypted_call_encrypted(10000) |
0.000 |
19.350 |
24.242 |
14.314 |
17.908 |
encrypted_call_unencrypted(10000) |
0.000 |
0.170 |
0.288 |
0.177 |
0.170 |
unencrypted_call_encrypted(10000) |
0.001 |
19.174 |
24.142 |
14.065 |
17.787 |
call_system |
0.000 |
0.016 |
0.025 |
0.014 |
0.009 |
mandel |
0.026 |
16.069 |
13.500 |
53.789 |
7.149 |
mandel2 |
0.044 |
13.562 |
18.659 |
81.108 |
9.687 |
ackermann(4) |
0.000 |
23.804 |
31.935 |
23.937 |
21.170 |
ary(50000) |
0.005 |
0.236 |
0.309 |
0.249 |
0.134 |
ary2(50000) |
0.003 |
0.087 |
0.069 |
0.084 |
0.064 |
ary3(2000) |
0.025 |
8.656 |
7.774 |
17.302 |
3.465 |
fibo(15) |
0.000 |
4.135 |
5.332 |
3.951 |
3.812 |
hash1(50000) |
0.005 |
1.128 |
1.685 |
1.115 |
0.939 |
hash2(500) |
0.005 |
0.917 |
0.724 |
2.194 |
0.424 |
heapsort(1000) |
0.001 |
2.100 |
2.676 |
1.912 |
1.938 |
matrix(20) |
0.012 |
2.172 |
2.602 |
6.838 |
1.331 |
nestedloop(12) |
0.018 |
5.564 |
5.353 |
5.140 |
2.714 |
sieve(30) |
0.007 |
2.008 |
3.029 |
5.675 |
1.056 |
strcat(200000) |
0.003 |
5.854 |
6.791 |
5.559 |
5.343 |
PHP 8.4
- docker run --rm -it php:8.4-apache /bin/bash
- PHP 8.4.3 (cli) (built: Jan 17 2025 17:31:49) (NTS)
- PHP 5.2测试需要额外增加命令行参数
-dmemory_limit=1000M
标识 |
未加密 |
推荐 |
PHP 5.2 |
最大保护 |
最大性能 |
simple |
0.008 |
3.671 |
3.902 |
3.665 |
1.830 |
encrypted_call_encrypted(10000) |
0.000 |
19.971 |
25.537 |
14.743 |
18.592 |
encrypted_call_unencrypted(10000) |
0.000 |
0.175 |
0.292 |
0.179 |
0.171 |
unencrypted_call_encrypted(10000) |
0.001 |
19.721 |
25.050 |
14.558 |
18.199 |
call_system |
0.000 |
0.015 |
0.025 |
0.015 |
0.009 |
mandel |
0.075 |
16.030 |
13.418 |
58.460 |
7.085 |
mandel2 |
0.084 |
13.620 |
18.712 |
82.202 |
9.325 |
ackermann(4) |
0.000 |
24.338 |
34.438 |
25.892 |
21.640 |
ary(50000) |
0.005 |
0.229 |
0.311 |
0.267 |
0.139 |
ary2(50000) |
0.003 |
0.087 |
0.070 |
0.089 |
0.064 |
ary3(2000) |
0.025 |
8.980 |
7.961 |
19.034 |
3.468 |
fibo(15) |
0.000 |
4.417 |
5.580 |
4.516 |
3.888 |
hash1(50000) |
0.005 |
1.151 |
1.719 |
1.145 |
0.959 |
hash2(500) |
0.006 |
0.906 |
0.728 |
2.323 |
0.420 |
heapsort(1000) |
0.001 |
2.135 |
2.772 |
2.018 |
1.984 |
matrix(20) |
0.014 |
2.150 |
2.659 |
7.335 |
1.357 |
nestedloop(12) |
0.016 |
5.502 |
5.512 |
5.453 |
2.774 |
sieve(30) |
0.009 |
1.996 |
3.112 |
6.045 |
1.028 |
strcat(200000) |
0.003 |
6.002 |
6.805 |
5.633 |
5.516 |
PHP 7.4
- docker run --rm -it php:7.4-apache /bin/bash
- PHP 7.4.33 (cli) (built: Nov 15 2022 06:03:30) ( NTS )
- 增加命令行参数
-dmemory_limit=1000M
标识 |
未加密 |
推荐 |
PHP 5.2 |
最大保护 |
最大性能 |
simple |
0.014 |
3.845 |
3.930 |
3.975 |
1.914 |
encrypted_call_encrypted(10000) |
0.000 |
18.922 |
24.386 |
14.627 |
16.599 |
encrypted_call_unencrypted(10000) |
0.000 |
0.144 |
0.264 |
0.153 |
0.143 |
unencrypted_call_encrypted(10000) |
0.001 |
18.700 |
24.109 |
14.472 |
16.417 |
call_system |
0.000 |
0.016 |
0.026 |
0.016 |
0.009 |
mandel |
0.081 |
16.514 |
13.856 |
58.369 |
7.132 |
mandel2 |
0.096 |
14.024 |
19.614 |
85.275 |
9.465 |
ackermann(4) |
0.000 |
23.719 |
36.032 |
27.104 |
20.108 |
ary(50000) |
0.005 |
0.237 |
0.323 |
0.289 |
0.145 |
ary2(50000) |
0.003 |
0.092 |
0.073 |
0.096 |
0.071 |
ary3(2000) |
0.030 |
8.899 |
8.098 |
19.255 |
3.753 |
fibo(15) |
0.000 |
4.242 |
5.233 |
4.523 |
3.569 |
hash1(50000) |
0.007 |
1.026 |
1.571 |
1.017 |
0.845 |
hash2(500) |
0.006 |
0.934 |
0.751 |
2.348 |
0.463 |
heapsort(1000) |
0.001 |
2.058 |
2.673 |
2.008 |
1.784 |
matrix(20) |
0.015 |
2.238 |
2.709 |
7.545 |
1.411 |
nestedloop(12) |
0.030 |
5.725 |
5.659 |
5.692 |
3.217 |
sieve(30) |
0.009 |
2.010 |
3.210 |
6.327 |
1.114 |
strcat(200000) |
0.004 |
5.457 |
6.434 |
5.429 |
4.959 |
PHP 5.6
- docker run --rm -it php:5.6-apache /bin/bash
- PHP 5.6.40 (cli) (built: Jan 23 2019 00:10:05)
- 增加命令行参数
-dmemory_limit=1000M
标识 |
未加密 |
推荐 |
PHP 5.2 |
最大保护 |
最大性能 |
simple |
0.064 |
22.914 |
16.394 |
12.584 |
7.677 |
encrypted_call_encrypted(10000) |
0.001 |
41.540 |
65.720 |
44.381 |
30.851 |
encrypted_call_unencrypted(10000) |
0.001 |
0.277 |
0.467 |
0.268 |
0.235 |
unencrypted_call_encrypted(10000) |
0.008 |
42.540 |
64.103 |
44.686 |
30.798 |
call_system |
0.001 |
0.087 |
0.094 |
0.052 |
0.032 |
mandel |
0.146 |
81.516 |
46.456 |
204.013 |
29.362 |
mandel2 |
0.195 |
63.136 |
65.535 |
277.859 |
41.093 |
ackermann(4) |
0.002 |
50.747 |
92.064 |
85.670 |
38.138 |
ary(50000) |
0.017 |
1.244 |
1.313 |
1.086 |
0.637 |
ary2(50000) |
0.013 |
0.447 |
0.357 |
0.432 |
0.371 |
ary3(2000) |
0.122 |
45.292 |
32.561 |
73.073 |
147.304 |
fibo(15) |
0.000 |
8.635 |
15.639 |
16.099 |
7.971 |
hash1(50000) |
0.021 |
2.965 |
3.637 |
2.933 |
1.694 |
hash2(500) |
0.017 |
12.909 |
13.632 |
13.244 |
9.913 |
heapsort(1000) |
0.002 |
7.268 |
10.314 |
9.381 |
7.315 |
matrix(20) |
0.060 |
12.344 |
12.749 |
28.213 |
7.068 |
nestedloop(12) |
0.080 |
32.938 |
24.304 |
26.064 |
13.126 |
sieve(30) |
0.055 |
10.280 |
11.729 |
28.281 |
10.368 |
strcat(200000) |
0.007 |
9.445 |
9.314 |
7.101 |
6.277 |
Total |
0.812 |
446.525 |
486.382 |
875.420 |
390.231 |
测试代码
<?php
if (function_exists("date_default_timezone_set")) {
date_default_timezone_set("UTC");
}
function simple() {
$a = 0;
for ($i = 0; $i < 1000000; $i++)
$a++;
$thisisanotherlongname = 0;
for ($thisisalongname = 0; $thisisalongname < 1000000; $thisisalongname++)
$thisisanotherlongname++;
}
/****/
function call_system() {
for ($i = 0; $i < 10000; $i++)
strlen("hallo");
}
/****/
function hallo($a) {
}
function encrypted_call_encrypted($n) {
for ($i = 0; $i < $n; $i++)
hallo("hallo");
}
/****/
function encrypted_call_unencrypted($n) {
for ($i = 0; $i < $n; $i++)
hallo2("hallo");
}
/**
* @Z5NotEncrypt
*/
function unencrypted_call_encrypted($n) {
for ($i = 0; $i < $n; $i++)
hallo("hallo");
}
/**
* @Z5NotEncrypt
*/
function hallo2($a) {
}
/****/
function mandel() {
$w1=50;
$h1=150;
$recen=-.45;
$imcen=0.0;
$r=0.7;
$s=0; $rec=0; $imc=0; $re=0; $im=0; $re2=0; $im2=0;
$x=0; $y=0; $w2=0; $h2=0; $color=0;
$s=2*$r/$w1;
$w2=40;
$h2=12;
for ($y=0 ; $y<=$w1; $y=$y+1) {
$imc=$s*($y-$h2)+$imcen;
for ($x=0 ; $x<=$h1; $x=$x+1) {
$rec=$s*($x-$w2)+$recen;
$re=$rec;
$im=$imc;
$color=1000;
$re2=$re*$re;
$im2=$im*$im;
while( ((($re2+$im2)<1000000) && $color>0)) {
$im=$re*$im*2+$imc;
$re=$re2-$im2+$rec;
$re2=$re*$re;
$im2=$im*$im;
$color=$color-1;
}
if ( $color==0 ) {
print "_";
} else {
print "#";
}
}
print "<br>";
flush();
}
}
/****/
function mandel2() {
$b = " .:,;!/>)|&IH%*#";
//float r, i, z, Z, t, c, C;
for ($y=30; printf("\n"), $C = $y*0.1 - 1.5, $y--;){
for ($x=0; $c = $x*0.04 - 2, $z=0, $Z=0, $x++ < 75;){
for ($r=$c, $i=$C, $k=0; $t = $z*$z - $Z*$Z + $r, $Z = 2*$z*$Z + $i, $z=$t, $k<5000; $k++)
if ($z*$z + $Z*$Z > 500000) break;
echo $b[$k%16];
}
}
}
/****/
function Ack($m, $n){
if($m == 0) return $n+1;
if($n == 0) return Ack($m-1, 1);
return Ack($m - 1, Ack($m, ($n - 1)));
}
function ackermann($n) {
$r = Ack(3,$n);
print "Ack(3,$n): $r\n";
}
/****/
function ary($n) {
for ($i=0; $i<$n; $i++) {
$X[$i] = $i;
}
for ($i=$n-1; $i>=0; $i--) {
$Y[$i] = $X[$i];
}
$last = $n-1;
print "$Y[$last]\n";
}
/****/
function ary2($n) {
for ($i=0; $i<$n;) {
$X[$i] = $i; ++$i;
$X[$i] = $i; ++$i;
$X[$i] = $i; ++$i;
$X[$i] = $i; ++$i;
$X[$i] = $i; ++$i;
$X[$i] = $i; ++$i;
$X[$i] = $i; ++$i;
$X[$i] = $i; ++$i;
$X[$i] = $i; ++$i;
$X[$i] = $i; ++$i;
}
for ($i=$n-1; $i>=0;) {
$Y[$i] = $X[$i]; --$i;
$Y[$i] = $X[$i]; --$i;
$Y[$i] = $X[$i]; --$i;
$Y[$i] = $X[$i]; --$i;
$Y[$i] = $X[$i]; --$i;
$Y[$i] = $X[$i]; --$i;
$Y[$i] = $X[$i]; --$i;
$Y[$i] = $X[$i]; --$i;
$Y[$i] = $X[$i]; --$i;
$Y[$i] = $X[$i]; --$i;
}
$last = $n-1;
print "$Y[$last]\n";
}
/****/
function ary3($n) {
for ($i=0; $i<$n; $i++) {
$X[$i] = $i + 1;
$Y[$i] = 0;
}
for ($k=0; $k<1000; $k++) {
for ($i=$n-1; $i>=0; $i--) {
$Y[$i] += $X[$i];
}
}
$last = $n-1;
print "$Y[0] $Y[$last]\n";
}
/****/
function fibo_r($n){
return(($n < 2) ? 1 : fibo_r($n - 2) + fibo_r($n - 1));
}
function fibo($n) {
$r = fibo_r($n);
print "$r\n";
}
/****/
function hash1($n) {
for ($i = 1; $i <= $n; $i++) {
$X[dechex($i)] = $i;
}
$c = 0;
for ($i = $n; $i > 0; $i--) {
if ($X[dechex($i)]) { $c++; }
}
print "$c\n";
}
/****/
function hash2($n) {
for ($i = 0; $i < $n; $i++) {
$hash1["foo_$i"] = $i;
$hash2["foo_$i"] = 0;
}
for ($i = $n; $i > 0; $i--) {
foreach($hash1 as $key => $value) $hash2[$key] += $value;
}
$first = "foo_0";
$last = "foo_".($n-1);
print "$hash1[$first] $hash1[$last] $hash2[$first] $hash2[$last]\n";
}
/****/
function gen_random ($n) {
global $LAST;
return( ($n * ($LAST = ($LAST * IA + IC) % IM)) / IM );
}
function heapsort_r($n, &$ra) {
$l = ($n >> 1) + 1;
$ir = $n;
while (1) {
if ($l > 1) {
$rra = $ra[--$l];
} else {
$rra = $ra[$ir];
$ra[$ir] = $ra[1];
if (--$ir == 1) {
$ra[1] = $rra;
return;
}
}
$i = $l;
$j = $l << 1;
while ($j <= $ir) {
if (($j < $ir) && ($ra[$j] < $ra[$j+1])) {
$j++;
}
if ($rra < $ra[$j]) {
$ra[$i] = $ra[$j];
$j += ($i = $j);
} else {
$j = $ir + 1;
}
}
$ra[$i] = $rra;
}
}
function heapsort($N) {
global $LAST;
define("IM", 139968);
define("IA", 3877);
define("IC", 29573);
$LAST = 42;
for ($i=1; $i<=$N; $i++) {
$ary[$i] = gen_random(1);
}
heapsort_r($N, $ary);
printf("%.10f\n", $ary[$N]);
}
/****/
function mkmatrix ($rows, $cols) {
$count = 1;
$mx = array();
for ($i=0; $i<$rows; $i++) {
for ($j=0; $j<$cols; $j++) {
$mx[$i][$j] = $count++;
}
}
return($mx);
}
function mmult ($rows, $cols, $m1, $m2) {
$m3 = array();
for ($i=0; $i<$rows; $i++) {
for ($j=0; $j<$cols; $j++) {
$x = 0;
for ($k=0; $k<$cols; $k++) {
$x += $m1[$i][$k] * $m2[$k][$j];
}
$m3[$i][$j] = $x;
}
}
return($m3);
}
function matrix($n) {
$SIZE = 30;
$m1 = mkmatrix($SIZE, $SIZE);
$m2 = mkmatrix($SIZE, $SIZE);
while ($n--) {
$mm = mmult($SIZE, $SIZE, $m1, $m2);
}
print "{$mm[0][0]} {$mm[2][3]} {$mm[3][2]} {$mm[4][4]}\n";
}
/****/
function nestedloop($n) {
$x = 0;
for ($a=0; $a<$n; $a++)
for ($b=0; $b<$n; $b++)
for ($c=0; $c<$n; $c++)
for ($d=0; $d<$n; $d++)
for ($e=0; $e<$n; $e++)
for ($f=0; $f<$n; $f++)
$x++;
print "$x\n";
}
/****/
function sieve($n) {
$count = 0;
while ($n-- > 0) {
$count = 0;
$flags = range (0,8192);
for ($i=2; $i<8193; $i++) {
if ($flags[$i] > 0) {
for ($k=$i+$i; $k <= 8192; $k+=$i) {
$flags[$k] = 0;
}
$count++;
}
}
}
print "Count: $count\n";
}
/****/
function strcat($n) {
$str = "";
while ($n-- > 0) {
$str .= "hello\n";
}
$len = strlen($str);
print "$len\n";
}
/*****/
/**
* @Z5NotEncrypt
*/
function gethrtime()
{
$hrtime = microtime(true);
return $hrtime;
}
/**
* @Z5NotEncrypt
*/
function start_test()
{
ob_start();
return gethrtime();
}
/**
* @Z5NotEncrypt
*/
function end_test($start, $name)
{
global $total;
$end = gethrtime();
ob_end_clean();
$total += $end-$start;
$num = number_format($end-$start,3);
$pad = str_repeat(" ", 50-strlen($name)-strlen($num));
echo $name.$pad.$num."\n";
ob_start();
return gethrtime();
}
/**
* @Z5NotEncrypt
*/
function total()
{
global $total;
$pad = str_repeat("-", 50);
echo $pad."\n";
$num = number_format($total,3);
$pad = str_repeat(" ", 50-strlen("Total")-strlen($num));
echo "Total".$pad.$num."\n";
}
echo "Start test...\n";
$t0 = $t = start_test();
simple();
$t = end_test($t, "simple");
encrypted_call_encrypted(10000);
$t = end_test($t, "encrypted_call_encrypted(10000)");
encrypted_call_unencrypted(10000);
$t = end_test($t, "encrypted_call_unencrypted(10000)");
unencrypted_call_encrypted(100000);
$t = end_test($t, "unencrypted_call_encrypted(10000)");
call_system();
$t = end_test($t, "call_system");
mandel();
$t = end_test($t, "mandel");
mandel2();
$t = end_test($t, "mandel2");
ackermann(4);
$t = end_test($t, "ackermann(4)");
ary(50000);
$t = end_test($t, "ary(50000)");
ary2(50000);
$t = end_test($t, "ary2(50000)");
ary3(2000);
$t = end_test($t, "ary3(2000)");
fibo(15);
$t = end_test($t, "fibo(15)");
hash1(50000);
$t = end_test($t, "hash1(50000)");
hash2(500);
$t = end_test($t, "hash2(500)");
heapsort(1000);
$t = end_test($t, "heapsort(1000)");
matrix(20);
$t = end_test($t, "matrix(20)");
nestedloop(12);
$t = end_test($t, "nestedloop(12)");
sieve(30);
$t = end_test($t, "sieve(30)");
strcat(200000);
$t = end_test($t, "strcat(200000)");
total();