PHP 在国产 CPU 上的编译与运行(四架构实战)

发布时间:2026/8/21 14:25:44
PHP 在国产 CPU 上的编译与运行(四架构实战) 第 1 章 PHP 在国产 CPU 上的编译与运行四架构实战1.1 为什么不能直接yum install php大白话版国产 OS 自带的 PHP 版本通常很老如 7.2、7.4而且扩展不全没有 Swoole、Redis、Imagick配置不符合生产要求短标签开着、错误提示关闭无法启用 JITPHP 8.0 的性能利器所以生产环境必须自己编译才能用最新版8.3.x获得性能提升装上 Swoole、Redis 等关键扩展对不同架构做针对性优化1.2 准备工作四架构通用# 1. 确认当前架构uname-m# 海光x86_64 飞腾/鲲鹏aarch64 龙芯loongarch64# 2. 装编译依赖麒麟 V10 用 yum统信 UOS 用 apt# 麒麟 V10sudoyuminstall-ygcc gcc-cmakeautoconf\libxml2-devel openssl-devel sqlite-devel\libcurl-devel libpng-devel libjpeg-devel\freetype-devel oniguruma-devel libzip-devel\systemd-devel readline-devel# 统信 UOSsudoaptinstall-ybuild-essential autoconf\libxml2-dev libssl-dev libsqlite3-dev\libcurl4-openssl-dev libpng-dev libjpeg-dev\libfreetype6-dev libonig-dev libzip-dev\libsystemd-dev libreadline-dev# 3. 下载 PHP 源码用国内镜像cd/usr/local/srcwgethttps://mirrors.tuna.tsinghua.edu.cn/php/php-8.3.10.tar.gztar-zxfphp-8.3.10.tar.gzcdphp-8.3.101.3 海光 x86_64 编译标准流程# 编译配置启用常用扩展 JIT FPM./configure\--prefix/usr/local/php8\--with-config-file-path/usr/local/php8/etc\--enable-fpm\--with-fpm-systemd\--with-fpm-userwww\--with-fpm-groupwww\--enable-mysqlnd\--with-pdo-mysqlmysqlnd\--with-mysqlimysqlnd\--with-openssl\--with-curl\--with-zlib\--enable-gd\--with-jpeg\--with-freetype\--enable-mbstring\--enable-bcmath\--enable-opcache\--enable-pcntl\--enable-sockets\--with-zip\--enable-soap\--enable-intl\--with-readline\--enable-sysvsem\--enable-sysvshm\--enable-sysvmsg# 编译用满 CPU 核心数make-j$(nproc)# 安装sudomakeinstall# 创建配置文件sudocpphp.ini-production /usr/local/php8/etc/php.inisudocpsapi/fpm/php-fpm.conf /usr/local/php8/etc/sudocpsapi/fpm/www.conf /usr/local/php8/etc/php-fpm.d/# 调整关键配置sudosed-is/;date.timezone /date.timezone Asia\/Shanghai//usr/local/php8/etc/php.inisudosed-is/upload_max_filesize 2M/upload_max_filesize 50M//usr/local/php8/etc/php.inisudosed-is/post_max_size 8M/post_max_size 50M//usr/local/php8/etc/php.inisudosed-is/memory_limit 128M/memory_limit 512M//usr/local/php8/etc/php.ini# 启用 JIT大幅提升计算密集型代码性能sudotee-a/usr/local/php8/etc/php.ini/dev/nullEOF [opcache] opcache.enable1 opcache.memory_consumption256 opcache.interned_strings_buffer16 opcache.max_accelerated_files10000 opcache.validate_timestamps0 opcache.jittracing opcache.jit_buffer_size128M EOF# 创建 FPM 用户sudogroupadd-rwwwsudouseradd-r-gwww-s/sbin/nologin-Mwww# 注册为 systemd 服务sudotee/etc/systemd/system/php-fpm.service/dev/nullEOF [Unit] DescriptionPHP 8.3 FastCGI Process Manager Afternetwork.target [Service] Typenotify ExecStart/usr/local/php8/sbin/php-fpm --nodaemonize --fpm-config /usr/local/php8/etc/php-fpm.conf ExecReload/bin/kill -USR2 $MAINPID PrivateTmptrue Restarton-failure [Install] WantedBymulti-user.target EOFsudosystemctl daemon-reloadsudosystemctlenablephp-fpmsudosystemctl start php-fpm# 验证/usr/local/php8/bin/php-v/usr/local/php8/bin/php-m|grepopcachesudosystemctl status php-fpm1.4 飞腾 / 鲲鹏 ARM64 编译差异点全列出大白话ARM64 和 x86 的区别在于「没有 x86 的那套 SIMD 指令」所以三件事要改configure要显式告诉它目标架构否则老的config.guess会认错-marchnative在 ARM 上要换成-mcpu鲲鹏 920 填tsv110飞腾填armv8-aJIT 在 PHP 8.3 的 ARM64 上是可用但不成熟生产建议只开 OPcache、关掉 JIT。cd/usr/local/src/php-8.3.10# 先确认 CPU 型号决定 -mcpu 参数lscpu|grep-imodel name# 鲲鹏 920 → tsv110 飞腾 FT-2000/S2500 → armv8-a保守但稳# 鲲鹏 920 用这套 CFLAGSexportCFLAGS-O2 -mcputsv110 -fno-strict-aliasing -pipeexportCXXFLAGS$CFLAGS# 飞腾用这套飞腾对 tsv110 不认会报 unknown value# export CFLAGS-O2 -mcpuarmv8-a -fno-strict-aliasing -pipe./configure\--prefix/usr/local/php8\--with-config-file-path/usr/local/php8/etc\--buildaarch64-linux-gnu\--hostaarch64-linux-gnu\--enable-fpm --with-fpm-systemd\--with-fpm-userwww --with-fpm-groupwww\--enable-mysqlnd --with-pdo-mysqlmysqlnd --with-mysqlimysqlnd\--with-openssl --with-curl --with-zlib\--enable-gd --with-jpeg --with-freetype\--enable-mbstring --enable-bcmath\--enable-opcache --enable-pcntl --enable-sockets\--with-zip --enable-soap --enable-intl --with-readline\--enable-sysvsem --enable-sysvshm --enable-sysvmsgmake-j$(nproc)sudomakeinstallARM64 上的php.ini与 x86 唯一的差别JIT 关掉[opcache] opcache.enable1 opcache.memory_consumption256 opcache.interned_strings_buffer16 opcache.max_accelerated_files10000 opcache.validate_timestamps0 ; ARM64 上 tracing JIT 在长跑进程里偶发段错误生产先关 opcache.jitdisable opcache.jit_buffer_size0验证是不是真的编成了 ARM64 原生二进制不是跑在翻译层上file/usr/local/php8/bin/php# 期望输出包含ELF 64-bit LSB executable, ARM aarch64/usr/local/php8/bin/php-recho PHP_INT_SIZE, PHP_EOL;# 期望 8/usr/local/php8/bin/php-recho php_uname(m), PHP_EOL;# 期望 aarch641.5 龙芯 LoongArch 编译最容易失败的一步大白话龙芯是自研指令集很多开源项目里的config.guess/config.sub用来猜当前架构的脚本还是几年前的版本根本不认识loongarch64于是直接报Invalid configuration ... machine loongarch64 not recognized。解决办法就是把这两个脚本换成新版。cd/usr/local/src/php-8.3.10# 第 1 步先看会不会报错./config.guess# 若报 unable to guess system type 或输出 unknown就要换脚本# 第 2 步换成 GNU 最新的 config.guess / config.sub#PHP 源码里这两个文件在 build/ 目录下wget-Obuild/config.guesshttps://git.savannah.gnu.org/gitweb/?pconfig.git;ablob_plain;fconfig.guess;hbHEADwget-Obuild/config.subhttps://git.savannah.gnu.org/gitweb/?pconfig.git;ablob_plain;fconfig.sub;hbHEADchmodx build/config.guess build/config.sub# 若机器不通外网就用系统 automake 自带的通常已支持 loongarch# sudo cp /usr/share/automake-*/config.guess build/config.guess# sudo cp /usr/share/automake-*/config.sub build/config.sub# 第 3 步确认现在能认出来了./build/config.guess# 期望loongarch64-unknown-linux-gnu# 第 4 步编译exportCFLAGS-O2 -marchloongarch64 -mabilp64d -fno-strict-aliasing -pipeexportCXXFLAGS$CFLAGS./configure\--prefix/usr/local/php8\--with-config-file-path/usr/local/php8/etc\--buildloongarch64-linux-gnu\--hostloongarch64-linux-gnu\--enable-fpm --with-fpm-systemd\--with-fpm-userwww --with-fpm-groupwww\--enable-mysqlnd --with-pdo-mysqlmysqlnd --with-mysqlimysqlnd\--with-openssl --with-curl --with-zlib\--enable-gd --with-jpeg --with-freetype\--enable-mbstring --enable-bcmath\--enable-opcache --enable-pcntl --enable-sockets\--with-zip --enable-soap --with-readline\--enable-sysvsem --enable-sysvshm --enable-sysvmsg# 注意intl 依赖 ICU龙芯上 ICU 版本常偏低装不上就先去掉 --enable-intlmake-j$(nproc)sudomakeinstall龙芯上 JIT 的现状重要PHP 的 JIT 后端只实现了 x86/x86_64 和 aarch64LoongArch 没有 JIT 后端。所以opcache.jit在龙芯上写了也不生效别浪费时间调它把 OPcache 开好就是最大收益。[opcache] opcache.enable1 opcache.memory_consumption192 opcache.interned_strings_buffer16 opcache.max_accelerated_files10000 opcache.validate_timestamps0 ; LoongArch 无 JIT 后端此项无效显式关闭避免误会 opcache.jitdisable1.6 装扩展三种方式按成功率排序方式 1pecl最省事海光/ARM64 大多能成exportPATH/usr/local/php8/bin:$PATH/usr/local/php8/bin/peclinstallredis /usr/local/php8/bin/peclinstallswoole# 装完在 php.ini 里加 extensionredis.so / extensionswoole.so方式 2源码编译pecl 失败时用龙芯首选# 以 redis 扩展为例cd/usr/local/srcwgethttps://github.com/phpredis/phpredis/archive/refs/tags/6.0.2.tar.gz-Ophpredis-6.0.2.tar.gztar-zxfphpredis-6.0.2.tar.gzcdphpredis-6.0.2 /usr/local/php8/bin/phpize# 龙芯/ARM 上如果 phpize 后 configure 报架构不认同样换 config.guess/config.sub./configure --with-php-config/usr/local/php8/bin/php-configmake-j$(nproc)sudomakeinstallechoextensionredis.so|sudotee-a/usr/local/php8/etc/php.ini方式 3改源码打补丁扩展里有 x86 汇编时典型报错长这样error: asm undeclared / impossible constraint in asm error: #error Unsupported architecture这说明扩展作者写了只在 x86 下能编的内联汇编。处理办法是关掉它的 SIMD/汇编优化开关走纯 C 回退路径# igbinary 在部分 ARM/龙芯环境需要禁用 SSE 相关优化./configure --with-php-config/usr/local/php8/bin/php-config\--disable-igbinary-sse# 具体开关名看该扩展 configure --help# 通用兜底让编译器忽略未知 pragma并降优化级别exportCFLAGS-O1 -fno-strict-aliasing -Wno-unknown-pragmas1.7 四架构编译结果对照同一份代码同一套参数下面这段脚本可以在任意架构上跑用来横向对比。注意这是采集方法不是我替你测出的结论具体数字取决于你机器的主频、内存和内核版本。sudotee/usr/local/bin/php-arch-bench.sh/dev/nullEOF #!/bin/bash # 用途采集当前架构下 PHP 的基础性能指标用于四架构横向对比 PHP/usr/local/php8/bin/php echo 环境信息 echo 架构 : $(uname -m) echo 内核 : $(uname -r) echo CPU 型号 : $(lscpu | grep -i model name | head -1 | cut -d: -f2 | xargs) echo 核心数 : $(nproc) echo PHP 版本 : $($PHP -r echo PHP_VERSION;) echo OPcache : $($PHP -r echo ini_get(opcache.enable) ? on : off;) echo JIT : $($PHP -r echo ini_get(opcache.jit) ?: n/a;) echo -e \n 1. 纯计算斐波那契递归测函数调用开销 $PHP -r $tmicrotime(true); function fib($n){ return $n2 ? $n : fib($n-1)fib($n-2); } fib(27); printf(耗时 %.3f 秒\n, microtime(true)-$t); echo -e \n 2. 字符串处理测内存分配 拷贝 $PHP -r $tmicrotime(true); $s; for($i0;$i300000;$i){ $s . md5((string)$i); if(strlen($s)2000000) $s; } printf(耗时 %.3f 秒\n, microtime(true)-$t); echo -e \n 3. 数组操作测哈希表性能 $PHP -r $tmicrotime(true); $a[]; for($i0;$i800000;$i){ $a[k$i]$i; } $sum0; foreach($a as $v){ $sum$v; } printf(耗时 %.3f 秒校验和 %d\n, microtime(true)-$t, $sum); echo -e \n 4. JSON 编解码测真实业务常见负载 $PHP -r $row[id1,name测试数据,tags[a,b,c],tstime()]; $dataarray_fill(0,2000,$row); $tmicrotime(true); for($i0;$i200;$i){ $jjson_encode($data); json_decode($j,true); } printf(耗时 %.3f 秒\n, microtime(true)-$t); EOFsudochmodx /usr/local/bin/php-arch-bench.sh php-arch-bench.sh|tee/tmp/bench-$(uname-m).txt把四台机器的/tmp/bench-*.txt收到一起就是你交给项目组的架构选型依据。经验上的定性结论不是具体倍数海光因为兼容 x86 且有 JIT纯计算类最快鲲鹏/飞腾在多核并发场景下靠核心数扳回来龙芯单核弱一些且无 JIT适合 I/O 密集型的 Web 业务。