PHP循环脚本耗时远超Java/Golang的原因排查
为什么简单循环的PHP脚本比Java/Golang慢这么多?
我编写的PHP循环脚本执行耗时32秒,而实现相同逻辑的Java脚本仅需约2毫秒,Golang脚本需200毫秒。已知PHP是解释型语言,会在解释器内部执行更多指令,但该代码逻辑非常简单,想了解是否存在其他导致耗时的原因。
环境信息
php version: PHP 7.4.3-4ubuntu2.19 (cli), Zend Engine v3.4.0 hardware: 15G RAM, 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz software: ubuntu 20.04 LTS on Windows WSL2.
测试代码
PHP代码
<?php function test(int $max, int $start) { $time_start = microtime(true); while ($start < $max) { $start = $start+1; } $time_end = microtime(true); //dividing with 60 will give the execution time in minutes otherwise seconds $execution_time = ($time_end - $time_start); //execution time of the script print('Total Execution Time: '.$execution_time.' Seconds \n'); } test(1000000000, 0);
Java代码
import java.time.Duration; import java.time.Instant; import java.util.ArrayList; import java.io.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.ThreadLocalRandom; import javax.swing.*; class Benchmark { public static void main(String args[]) { int max = 1000000000; int index = 0; long start = System.currentTimeMillis(); while(index < max) { index++; } long end = System.currentTimeMillis(); System.out.println("Elapsed Time in millseconds: "+ (end-start)); System.out.println("index: "+ index); } }
核心原因分析
JIT编译缺失(PHP 7.4):你使用的PHP 7.4默认未开启JIT(即时编译)功能。Java的HotSpot虚拟机运行时会将热点代码编译为机器码直接执行,Golang本身是编译型语言,直接生成机器码。而PHP的Zend引擎在未开启JIT时,只能逐行解释执行代码,10亿次循环的解释开销被无限放大。
软类型的运行时校验:尽管PHP函数参数加了
int类型声明,但PHP的类型声明是“软约束”,运行时仍会对变量类型做校验。每次$start = $start+1操作都要额外检查变量类型,而Java的int是原生值类型,编译阶段就确定了类型,运行时无额外校验开销。单指令的执行开销差异:PHP的每条操作都会被Zend引擎拆解为多条内部指令执行,比如
$start++对应的Zend指令逻辑远复杂于Java字节码最终编译出的机器码。单步操作的微小开销,在10亿次循环后会累积成巨大的时间差。WSL2的额外影响:虽然Java和Golang也在WSL2环境运行,但解释型语言的指令调度、内存交互在WSL2下的额外开销比编译型语言更显著。解释器需要频繁与宿主系统交互,而编译后的程序更贴近原生系统执行,开销更低。
内容的提问来源于stack exchange,提问作者Wallace
相关产品推荐
相关产品推荐

