PHP信创=飞腾FT系列处理器PHP运行环境适配与性能调优
·
--- 一、先搞清楚飞腾是什么(大白话)
┌──────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 概念 │ 大白话解释 │
├──────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 飞腾FT系 │ 国产ARM芯片,指令集是ARMv8/ARMv9,和手机CPU同根同源,但面向服务器 │
│ 列 │ │
├──────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ aarch64 │ ARM 64位架构的代号,飞腾跑的就是这个 │
├──────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ NUMA │ "非均匀内存访问",FT2500有16个NUMA节点,每个节点8个核心;进程跨节点访问内存会慢很多,就像你去隔壁城 │
│ │ 市买早饭,太远了 │
├──────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ JIT │ PHP8的即时编译,把PHP代码编译成机器码直接跑;飞腾ARM64原生支持JIT(不像龙芯需要禁用) │
├──────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ OPcache │ PHP字节码缓存,把编译好的中间代码存内存里,省去重复解析 │
├──────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 绑核 │ 把进程锁定在特定CPU核心上跑,防止它到处乱跳浪费时间 │
└──────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────┘
飞腾处理器家族一览:
┌─────────────┬─────────┬──────────────┬───────────────────────────┐
│ 型号 │ 核心数 │ 场景 │ 注意点 │
├─────────────┼─────────┼──────────────┼───────────────────────────┤
│ FT-2000/4 │ 4核 │ 桌面 │ 单路,NUMA简单 │
├─────────────┼─────────┼──────────────┼───────────────────────────┤
│ FT-2000+/64 │ 64核 │ 服务器 │ 多NUMA节点,需绑核 │
├─────────────┼─────────┼──────────────┼───────────────────────────┤
│ FT-2500 │ 64核/路 │ 高性能服务器 │ 16 NUMA节点,绑核至关重要 │
├─────────────┼─────────┼──────────────┼───────────────────────────┤
│ D2000 │ 8核 │ 桌面/嵌入式 │ 兼容FT-2000/4设计 │
└─────────────┴─────────┴──────────────┴───────────────────────────┘
---
二、环境确认
# 1. 确认架构(必须是 aarch64)
uname -m
# 期望输出:aarch64
# 2. 查看飞腾CPU详情
cat /proc/cpuinfo | grep "model name" | head -1
# 期望类似:Phytium, FT-2000+/64
# 3. 查看NUMA拓扑(这个对FT2500很重要!)
numactl --hardware
# 会显示有几个NUMA节点、每个节点多少核、各节点内存距离
# 4. 查看操作系统(飞腾常用国产系统)
cat /etc/os-release
# 5. 查看GCC版本(需要9.3+才能完整支持ARMv8特性)
gcc --version
NUMA拓扑输出示例(FT2500双路):
available: 16 nodes (0-15)
node 0 cpus: 0 1 2 3 4 5 6 7
node 0 size: 16126 MB
node 0 free: 14200 MB
...
node distances:
node 0 1 2 ...
0: 10 15 20 ... # 10=本地,数字越大越远,代价越高
---
三、安装编译依赖
银河麒麟 V10 / 统信 UOS(Debian系)
sudo apt update && sudo apt upgrade -y
sudo apt install -y \
build-essential \
gcc \
g++ \
make \
cmake \
autoconf \
bison \
re2c \
pkg-config \
numactl \
libnuma-dev \
libxml2-dev \
libssl-dev \
libcurl4-openssl-dev \
libpng-dev \
libjpeg-dev \
libwebp-dev \
libfreetype-dev \
libzip-dev \
zlib1g-dev \
libsqlite3-dev \
libonig-dev \
libreadline-dev \
libsodium-dev \
libgmp-dev \
libffi-dev \
libicu-dev \
libbz2-dev \
libxslt-dev
中标麒麟 / openEuler / 华为云(Fedora/RPM系)
sudo yum update -y
sudo yum install -y \
gcc \
gcc-c++ \
make \
autoconf \
bison \
re2c \
pkg-config \
numactl \
numactl-devel \
libxml2-devel \
openssl-devel \
libcurl-devel \
libpng-devel \
libjpeg-devel \
libwebp-devel \
freetype-devel \
libzip-devel \
zlib-devel \
sqlite-devel \
oniguruma-devel \
readline-devel \
libsodium-devel \
gmp-devel \
libffi-devel \
libicu-devel \
bzip2-devel \
libxslt-devel
为什么要装 numactl? 飞腾NUMA架构的核心调优工具,没它PHP-FPM在跨NUMA访问时性能会差4倍。
---
四、下载PHP源码并配置编译参数
4.1 下载源码
mkdir -p /opt/php-build
cd /opt/php-build
# 推荐PHP 8.3(ARM64 JIT最成熟)
PHP_VERSION="8.3.10"
wget "https://www.php.net/distributions/php-${PHP_VERSION}.tar.gz"
tar -xzf "php-${PHP_VERSION}.tar.gz"
cd "php-${PHP_VERSION}"
4.2 飞腾ARM64专用编译配置
关键点: 飞腾是正宗ARM64,可以用 -march=armv8-a 开启ARM原生优化,还可以 开启JIT(龙芯不行,飞腾可以)。
# 设置编译优化标志(飞腾ARM64专用)
export CFLAGS="-O2 -march=armv8-a+simd -funroll-loops -fomit-frame-pointer"
export CXXFLAGS="$CFLAGS"
export LDFLAGS="-Wl,-O1"
./configure \
--prefix=/usr/local/php \
--with-config-file-path=/usr/local/php/etc \
--with-config-file-scan-dir=/usr/local/php/etc/php.d \
--with-libdir=lib64 \
--enable-fpm \
--with-fpm-user=www \
--with-fpm-group=www \
--enable-opcache \
--enable-mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-mysqli=mysqlnd \
--with-pdo-sqlite \
--with-openssl \
--with-curl \
--with-zlib \
--enable-mbstring \
--enable-bcmath \
--enable-gd \
--with-jpeg \
--with-png \
--with-webp \
--with-freetype \
--with-zip \
--enable-soap \
--enable-xml \
--enable-json \
--enable-ctype \
--enable-tokenizer \
--enable-fileinfo \
--enable-dom \
--enable-simplexml \
--enable-xmlreader \
--enable-xmlwriter \
--enable-phar \
--enable-filter \
--enable-session \
--with-readline \
--enable-sockets \
--enable-pcntl \
--enable-posix \
--with-sodium \
--with-gmp \
--enable-intl \
--enable-calendar \
--with-bz2 \
--with-xsl \
2>&1 | tee /opt/php-build/configure.log
# 检查configure是否成功
echo $? # 输出0表示成功
与龙芯配置的关键差异:
┌───────────────┬───────────────────────┬─────────────────────────────────────┐
│ 参数 │ 龙芯 │ 飞腾 │
├───────────────┼───────────────────────┼─────────────────────────────────────┤
│ JIT │ --disable-opcache-jit │ 不加这个,JIT默认开启 │
├───────────────┼───────────────────────┼─────────────────────────────────────┤
│ CFLAGS │ 无特殊 │ -march=armv8-a+simd 利用ARM向量指令 │
├───────────────┼───────────────────────┼─────────────────────────────────────┤
│ --with-libdir │ lib64 │ lib64 │
├───────────────┼───────────────────────┼─────────────────────────────────────┤
│ config.guess │ 必须更新 │ 无需,系统自带支持aarch64 │
└───────────────┴───────────────────────┴─────────────────────────────────────┘
---
五、编译和安装
# 查看CPU核心数
CORES=$(nproc)
echo "使用 ${CORES} 个核心编译"
# 开始编译
make -j${CORES} 2>&1 | tee /opt/php-build/make.log
# 检查编译错误(没输出说明成功)
grep -E "^make.*Error" /opt/php-build/make.log
# 安装
sudo make install
# 配置环境变量
echo 'export PATH=/usr/local/php/bin:/usr/local/php/sbin:$PATH' | sudo tee -a /etc/profile
source /etc/profile
# 验证
php -v
---
六、PHP核心配置(飞腾ARM64优化版)
6.1 复制基础配置
cp /opt/php-build/php-8.3.10/php.ini-production /usr/local/php/etc/php.ini
mkdir -p /usr/local/php/etc/php.d
mkdir -p /var/log/php
6.2 飞腾专属php.ini优化配置
cat > /usr/local/php/etc/php.d/phytium-optimize.ini << 'EOF'
; ================================================
; 飞腾FT系列ARM64 PHP性能优化配置
; ================================================
; ===== OPcache 基础配置 =====
; 开启OPcache(必须)
opcache.enable=1
; CLI也开启(对Swoole/WorkerMan等常驻进程有利)
opcache.enable_cli=1
; 共享内存256MB(多核服务器可以给到512MB)
opcache.memory_consumption=256
; 字符串缓冲区,减少重复字符串内存占用
opcache.interned_strings_buffer=32
; 最多缓存文件数,含vendor目录(Laravel约8000个文件)
opcache.max_accelerated_files=20000
; 生产环境关闭文件变动检查,提升性能(上线后手动清缓存)
opcache.validate_timestamps=0
opcache.revalidate_freq=0
; 保留注释(某些框架依赖注解)
opcache.save_comments=1
; ===== JIT配置(飞腾ARM64原生支持!)=====
; JIT模式:tracing=追踪热点代码路径,比function模式更彻底
; 也可以用数字1255:C=1(CPU优化) R=2(全局寄存器分配) T=5(追踪JIT) O=5(最高优化级别)
opcache.jit=tracing
; JIT缓冲区128MB(计算密集型业务可加到256MB)
opcache.jit_buffer_size=128M
; ===== 大页(Huge Pages)优化 =====
; 降低TLB缺失率,飞腾多核场景效果明显
; 前提:系统层要先开启大页(见下方系统配置)
opcache.huge_code_pages=1
; ===== 文件缓存(重启PHP后不用重新预热)=====
opcache.file_cache=/tmp/php-opcache
opcache.file_cache_consistency_checks=0
; ===== 预加载(PHP 7.4+,减少首次请求延迟)=====
; 指定预加载脚本(以Laravel为例,uncomment后填实际路径)
; opcache.preload=/var/www/html/preload.php
; opcache.preload_user=www
; ===== 基础性能配置 =====
memory_limit=512M
max_execution_time=60
upload_max_filesize=128M
post_max_size=128M
realpath_cache_size=4096K
realpath_cache_ttl=600
; ===== 错误日志(生产环境)=====
display_errors=Off
log_errors=On
error_log=/var/log/php/error.log
error_reporting=E_ALL & ~E_DEPRECATED & ~E_STRICT
; ===== 时区 =====
date.timezone=Asia/Shanghai
EOF
6.3 开启系统大页(Huge Pages)
# 大页是什么:默认内存按4KB分页,大页按2MB分页
# 好处:CPU的TLB(地址翻译缓存)条目变少,缺失率下降,内存访问更快
# 飞腾多核服务器内存带宽压力大,大页效果尤其明显
# 临时开启(重启失效)
echo 512 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# 永久生效
echo "vm.nr_hugepages=512" >> /etc/sysctl.conf
sysctl -p
# 验证
cat /proc/meminfo | grep Huge
# 输出应该包含:HugePages_Total: 512
---
七、飞腾最关键的调优:NUMA绑核
这是飞腾平台PHP调优最重要的一步,很多人忽略它,导致性能只有应有水平的1/4!
7.1 为什么飞腾必须绑核(大白话)
飞腾FT2500双路服务器内存结构(简化示意):
Socket 0 (64核,8个NUMA节点,各8核)
├── NUMA Node 0: Core 0-7 ←→ 内存A(就近访问,延迟10)
├── NUMA Node 1: Core 8-15 ←→ 内存B(就近访问,延迟10)
├── NUMA Node 2: Core 16-23 ←→ 内存C(就近访问,延迟10)
...
Socket 1 (64核,8个NUMA节点,各8核)
├── NUMA Node 8: Core 64-71 ←→ 内存I(就近访问)
...
跨NUMA访问延迟:15~20(是本地的1.5~2倍)
不绑核时PHP进程随机在16个节点乱跑,内存大量跨节点访问
→ IPC从正常的0.6跌到0.08,QPS只有应有水平的1/4
7.2 查看NUMA拓扑
# 查看NUMA节点和CPU分布
numactl --hardware
# 查看进程当前NUMA使用情况
numastat -p $(pgrep php-fpm | head -1)
# 查看NUMA节点的内存使用
numastat
7.3 创建NUMA感知的PHP-FPM启动脚本
cat > /usr/local/bin/start-php-fpm-numa.sh << 'EOF'
#!/bin/bash
# 飞腾FT系列 NUMA感知的PHP-FPM启动脚本
# 查询NUMA节点数量
NUMA_NODES=$(numactl --hardware | grep "available:" | awk '{print $2}')
echo "系统共有 ${NUMA_NODES} 个NUMA节点"
# 飞腾FT2500双路典型部署:绑定到node0和node1(同一socket内相邻节点)
# 根据实际NUMA拓扑调整节点编号
NUMA_BIND_NODES="0,1"
echo "将PHP-FPM绑定到NUMA节点: ${NUMA_BIND_NODES}"
numactl \
--cpunodebind=${NUMA_BIND_NODES} \
--membind=${NUMA_BIND_NODES} \
/usr/local/php/sbin/php-fpm \
--nodaemonize \
--fpm-config /usr/local/php/etc/php-fpm.conf
EOF
chmod +x /usr/local/bin/start-php-fpm-numa.sh
7.4 修改systemd服务使用NUMA绑核
cat > /etc/systemd/system/php-fpm.service << 'EOF'
[Unit]
Description=PHP FastCGI Process Manager (Phytium NUMA Optimized)
After=network.target
[Service]
Type=forking
PIDFile=/var/run/php-fpm.pid
# 飞腾FT2500:绑定到NUMA node 0和1,避免跨socket内存访问
# 根据实际numactl --hardware的输出调整
ExecStart=/usr/bin/numactl --cpunodebind=0,1 --membind=0,1 \
/usr/local/php/sbin/php-fpm \
--fpm-config /usr/local/php/etc/php-fpm.conf
ExecReload=/bin/kill -USR2 $MAINPID
PrivateTmp=true
LimitNOFILE=65535
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable php-fpm
7.5 多实例部署(高并发场景)
对于飞腾FT2500这种超多核服务器,可以按NUMA节点部署多个PHP-FPM实例:
# 每个NUMA节点一个PHP-FPM实例,各自使用本地内存
# 前置:Nginx按端口或socket负载均衡到多个实例
# 实例1:绑定NUMA node 0-1 (core 0-15),监听socket1
cat > /etc/systemd/system/php-fpm-numa0.service << 'EOF'
[Unit]
Description=PHP-FPM Instance NUMA Node 0-1
[Service]
ExecStart=/usr/bin/numactl --cpunodebind=0,1 --membind=0,1 \
/usr/local/php/sbin/php-fpm \
--fpm-config /usr/local/php/etc/php-fpm-numa0.conf
Restart=on-failure
EOF
# 实例2:绑定NUMA node 2-3 (core 16-31),监听socket2
cat > /etc/systemd/system/php-fpm-numa1.service << 'EOF'
[Unit]
Description=PHP-FPM Instance NUMA Node 2-3
[Service]
ExecStart=/usr/bin/numactl --cpunodebind=2,3 --membind=2,3 \
/usr/local/php/sbin/php-fpm \
--fpm-config /usr/local/php/etc/php-fpm-numa1.conf
Restart=on-failure
EOF
---
八、PHP-FPM进程池配置(飞腾多核优化)
# 创建www用户
groupadd www 2>/dev/null; useradd -g www -s /sbin/nologin -M www 2>/dev/null
# 主配置
cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf
# 进程池配置(飞腾多核优化版)
cat > /usr/local/php/etc/php-fpm.d/www.conf << 'EOF'
[www]
user = www
group = www
; Unix socket 比 TCP 快,推荐使用
listen = /var/run/php-fpm/www.sock
listen.owner = www
listen.group = www
listen.mode = 0660
; 飞腾多核服务器:dynamic模式,让系统自适应负载
pm = dynamic
; 最大子进程数计算公式:
; 单个PHP-FPM进程内存约50-80MB
; 绑定2个NUMA节点,可用内存约32GB
; max_children = 可用内存(MB) / 单进程内存(MB) = 32768 / 64 ≈ 512
; 保守值取一半:256
pm.max_children = 256
; 启动时创建进程数(建议 max_children 的 1/8)
pm.start_servers = 32
; 最少保持空闲进程数
pm.min_spare_servers = 16
; 最多保持空闲进程数
pm.max_spare_servers = 64
; 每个进程处理1000个请求后重启(防内存泄漏)
pm.max_requests = 1000
; 慢日志:请求超过2秒记录(排查慢接口)
request_slowlog_timeout = 2s
slowlog = /var/log/php/www-slow.log
; 状态页(Nginx监控用)
pm.status_path = /fpm-status
; 进程空闲超时(秒)
pm.process_idle_timeout = 60s
; 传递环境变量
env[PATH] = /usr/local/php/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
; 资源限制
php_admin_value[memory_limit] = 512M
php_admin_value[open_basedir] = /var/www/html:/tmp:/usr/local/php
EOF
# 创建日志目录
mkdir -p /var/run/php-fpm /var/log/php
chown www:www /var/run/php-fpm
---
九、安装常用扩展
9.1 Redis扩展
cd /opt/php-build
# 下载phpredis
wget https://github.com/phpredis/phpredis/archive/refs/tags/6.0.2.tar.gz -O phpredis-6.0.2.tar.gz
tar -xzf phpredis-6.0.2.tar.gz
cd phpredis-6.0.2
# phpize:准备扩展的构建环境
/usr/local/php/bin/phpize
# 编译
./configure --with-php-config=/usr/local/php/bin/php-config
# ARM64优化编译
CFLAGS="-O2 -march=armv8-a" make -j$(nproc)
sudo make install
echo "extension=redis.so" > /usr/local/php/etc/php.d/redis.ini
# 验证
php -m | grep -i redis
9.2 Swoole扩展(飞腾ARM64原生支持协程)
cd /opt/php-build
# Swoole 5.x 已原生支持aarch64协程上下文切换(汇编实现)
wget https://github.com/swoole/swoole-src/archive/refs/tags/v5.1.3.tar.gz -O swoole-5.1.3.tar.gz
tar -xzf swoole-5.1.3.tar.gz
cd swoole-src-5.1.3
/usr/local/php/bin/phpize
./configure \
--with-php-config=/usr/local/php/bin/php-config \
--enable-swoole-curl \
--enable-openssl \
--with-openssl-dir=/usr \
--enable-cares \
--enable-swoole-pgsql
CFLAGS="-O2 -march=armv8-a+simd" make -j$(nproc)
sudo make install
echo "extension=swoole.so" > /usr/local/php/etc/php.d/swoole.ini
# 验证ARM64支持
php --ri swoole | grep -E "arch|aarch64|context"
Swoole在飞腾上的亮点: Swoole的协程上下文切换底层用汇编写的,5.x版本有专门的aarch64实现(context/asm/jump_aarch64_sysv
_elf_gas.S),性能不输x86。
9.3 ImageMagick扩展
# 安装ImageMagick库(飞腾ARM64版本)
sudo apt install -y libmagickwand-dev # Debian系
# 或
sudo yum install -y ImageMagick-devel # RPM系
cd /opt/php-build
wget https://pecl.php.net/get/imagick-3.7.0.tgz
tar -xzf imagick-3.7.0.tgz
cd imagick-3.7.0
/usr/local/php/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make -j$(nproc)
sudo make install
echo "extension=imagick.so" > /usr/local/php/etc/php.d/imagick.ini
9.4 MongoDB扩展
/usr/local/php/bin/pecl install mongodb
echo "extension=mongodb.so" > /usr/local/php/etc/php.d/mongodb.ini
---
十、Nginx配置(配合飞腾多实例PHP-FPM)
# 下载Nginx
cd /opt
wget http://nginx.org/download/nginx-1.26.2.tar.gz
tar -xzf nginx-1.26.2.tar.gz
cd nginx-1.26.2
# 飞腾ARM64优化编译
./configure \
--prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-stream \
--with-stream_ssl_module \
--with-cc-opt="-O2 -march=armv8-a" \
--with-ld-opt="-Wl,-rpath,/usr/local/lib"
make -j$(nproc)
sudo make install
# /usr/local/nginx/conf/nginx.conf(飞腾多核优化版)
user www;
# worker进程数 = CPU核心数(飞腾FT2500单路64核)
worker_processes 64;
# 将worker进程绑定到CPU(飞腾多核利用)
# worker_cpu_affinity auto; # Nginx 1.9.10+支持自动绑核
worker_cpu_affinity auto;
# 错误日志
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
# 每个worker最大连接数
worker_connections 4096;
# 使用epoll(Linux最高效的IO多路复用)
use epoll;
# 一次接受所有新连接(飞腾高并发场景有利)
multi_accept on;
}
http {
include mime.types;
default_type application/octet-stream;
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $request_time';
# 基础优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 1000;
# Gzip压缩
gzip on;
gzip_comp_level 4;
gzip_types text/plain text/css application/json application/javascript;
# 上游PHP-FPM(多NUMA实例负载均衡)
upstream php_fpm {
# 使用最少连接策略
least_conn;
# NUMA node 0-1 的 PHP-FPM 实例
server unix:/var/run/php-fpm/www-numa0.sock weight=1;
# NUMA node 2-3 的 PHP-FPM 实例
server unix:/var/run/php-fpm/www-numa1.sock weight=1;
# 单实例场景直接用:
# server unix:/var/run/php-fpm/www.sock;
keepalive 32;
}
server {
listen 80;
server_name _;
root /var/www/html;
index index.php index.html;
access_log /var/log/nginx/access.log main;
# PHP处理
location ~ \.php$ {
fastcgi_pass php_fpm;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_connect_timeout 10;
fastcgi_send_timeout 60;
fastcgi_read_timeout 60;
fastcgi_buffer_size 64k;
fastcgi_buffers 8 64k;
}
# PHP-FPM状态监控(内网访问)
location /fpm-status {
allow 127.0.0.1;
deny all;
fastcgi_pass php_fpm;
fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
include fastcgi_params;
}
# 静态文件缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
}
}
---
十一、OPcache预加载(减少冷启动延迟)
<?php
// /var/www/html/preload.php
// PHP-FPM启动时执行,把框架核心文件预编译进内存
// 效果:首次请求不再需要解析这些文件,响应时间从200ms降到50ms
declare(strict_types=1);
$preloadDirs = [
// Laravel框架核心
__DIR__ . '/vendor/laravel/framework/src/Illuminate/Support',
__DIR__ . '/vendor/laravel/framework/src/Illuminate/Http',
__DIR__ . '/vendor/laravel/framework/src/Illuminate/Routing',
__DIR__ . '/vendor/laravel/framework/src/Illuminate/Container',
// ThinkPHP核心(如果用ThinkPHP)
// __DIR__ . '/vendor/topthink/framework/src',
];
$count = 0;
foreach ($preloadDirs as $dir) {
if (!is_dir($dir)) continue;
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS)
);
foreach ($iterator as $file) {
if ($file->getExtension() !== 'php') continue;
$path = $file->getPathname();
// 跳过测试文件(节省内存)
if (strpos($path, '/test') !== false || strpos($path, '/Test') !== false) {
continue;
}
if (opcache_compile_file($path)) {
$count++;
}
}
}
// 预加载完成后输出日志
error_log("OPcache预加载完成:共预加载 {$count} 个PHP文件");
; 在 phytium-optimize.ini 中添加
opcache.preload=/var/www/html/preload.php
opcache.preload_user=www
---
十二、性能验证脚本
#!/bin/bash
# /usr/local/bin/phytium-php-check.sh
# 飞腾PHP环境完整检查
echo "=============================================="
echo " 飞腾FT系列 PHP运行环境检查报告"
echo "=============================================="
# 1. 架构验证
echo ""
echo "【1】硬件环境"
echo "CPU架构: $(uname -m)"
echo "CPU型号: $(cat /proc/cpuinfo | grep 'model name' | head -1 | cut -d: -f2 | xargs)"
echo "CPU核心: $(nproc) 个"
echo "物理内存: $(free -g | awk '/^Mem:/{print $2}') GB"
# 2. NUMA信息
echo ""
echo "【2】NUMA拓扑"
if command -v numactl &>/dev/null; then
NUMA_NODES=$(numactl --hardware | grep "available:" | awk '{print $2}')
echo "NUMA节点数: ${NUMA_NODES}"
numactl --hardware | grep "node.*size"
else
echo "警告:numactl未安装,无法查看NUMA信息"
fi
# 3. PHP信息
echo ""
echo "【3】PHP环境"
PHP_BIN="/usr/local/php/bin/php"
if [ -f "$PHP_BIN" ]; then
echo "PHP版本: $($PHP_BIN -v | head -1)"
echo "PHP路径: $PHP_BIN"
else
echo "错误:PHP未找到"
exit 1
fi
# 4. OPcache和JIT
echo ""
echo "【4】OPcache/JIT状态"
$PHP_BIN -r "
\$status = opcache_get_status(false);
if (!\$status) {
echo 'OPcache: 未启用' . PHP_EOL;
} else {
echo 'OPcache: 已启用' . PHP_EOL;
echo 'JIT状态: ' . (\$status['jit']['enabled'] ?? false ? '已启用' : '未启用(检查jit_buffer_size配置)') .
PHP_EOL;
if (isset(\$status['jit']['kind'])) {
\$kinds = [0=>'禁用', 1=>'Function JIT', 2=>'Tracing JIT'];
echo 'JIT模式: ' . (\$kinds[\$status['jit']['kind']] ?? '未知') . PHP_EOL;
}
echo 'OPcache内存使用: ' . round(\$status['memory_usage']['used_memory']/1024/1024, 2) . 'MB' . PHP_EOL;
echo 'OPcache空闲内存: ' . round(\$status['memory_usage']['free_memory']/1024/1024, 2) . 'MB' . PHP_EOL;
echo '已缓存文件数: ' . \$status['opcache_statistics']['num_cached_scripts'] . PHP_EOL;
}
"
# 5. 扩展检查
echo ""
echo "【5】扩展状态"
for EXT in opcache redis swoole pdo_mysql gd mbstring json curl zip; do
STATUS=$($PHP_BIN -m | grep -w "$EXT" && echo "已安装" || echo "未安装")
printf " %-15s: %s\n" "$EXT" "$($PHP_BIN -m | grep -w "$EXT" > /dev/null && echo '✓ 已安装' || echo '✗ 未安装')"
done
# 6. PHP-FPM状态
echo ""
echo "【6】PHP-FPM服务"
if systemctl is-active php-fpm &>/dev/null; then
echo "PHP-FPM: 运行中"
echo "进程数: $(pgrep -c php-fpm)"
else
echo "PHP-FPM: 未运行"
fi
# 7. 大页状态
echo ""
echo "【7】系统大页(Huge Pages)"
HUGE_TOTAL=$(grep HugePages_Total /proc/meminfo | awk '{print $2}')
HUGE_FREE=$(grep HugePages_Free /proc/meminfo | awk '{print $2}')
echo "大页总数: ${HUGE_TOTAL}"
echo "空闲大页: ${HUGE_FREE}"
[ "$HUGE_TOTAL" -eq 0 ] && echo "警告:未开启大页,建议设置 vm.nr_hugepages=512"
# 8. 简单性能基准
echo ""
echo "【8】PHP性能基准测试"
$PHP_BIN -r "
\$start = microtime(true);
// 测试1:CPU计算
\$sum = 0;
for (\$i = 0; \$i < 1000000; \$i++) { \$sum += \$i; }
\$t1 = round((microtime(true) - \$start) * 1000, 2);
// 测试2:字符串操作
\$start2 = microtime(true);
\$str = '';
for (\$i = 0; \$i < 10000; \$i++) { \$str .= 'PHP on Phytium FT '; }
\$t2 = round((microtime(true) - \$start2) * 1000, 2);
// 测试3:数组操作
\$start3 = microtime(true);
\$arr = range(1, 100000);
shuffle(\$arr);
sort(\$arr);
\$t3 = round((microtime(true) - \$start3) * 1000, 2);
echo ' 100万次整数求和: ' . \$t1 . 'ms' . PHP_EOL;
echo ' 1万次字符串拼接: ' . \$t2 . 'ms' . PHP_EOL;
echo ' 10万元素排序: ' . \$t3 . 'ms' . PHP_EOL;
"
echo ""
echo "=============================================="
echo " 检查完成"
echo "=============================================="
chmod +x /usr/local/bin/phytium-php-check.sh
/usr/local/bin/phytium-php-check.sh
---
十三、完整一键编译脚本
#!/bin/bash
# build_php_phytium.sh
# 飞腾FT系列ARM64 PHP 8.3 一键编译安装脚本
# 使用:chmod +x build_php_phytium.sh && sudo bash build_php_phytium.sh
set -e
PHP_VERSION="8.3.10"
INSTALL_DIR="/usr/local/php"
BUILD_DIR="/opt/php-build"
PHP_USER="www"
CORES=$(nproc)
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; NC='\033[0m'
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERRO]${NC} $1"; }
# 验证架构
ARCH=$(uname -m)
if [ "$ARCH" != "aarch64" ]; then
log_warn "当前架构为 $ARCH,本脚本针对飞腾aarch64优化,请确认"
fi
log_info "架构: $ARCH,CPU核心: $CORES"
# 准备目录
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
# 下载PHP源码
if [ ! -f "php-${PHP_VERSION}.tar.gz" ]; then
log_info "下载 PHP ${PHP_VERSION}..."
wget -q "https://www.php.net/distributions/php-${PHP_VERSION}.tar.gz"
fi
if [ ! -d "php-${PHP_VERSION}" ]; then
log_info "解压源码..."
tar -xzf "php-${PHP_VERSION}.tar.gz"
fi
cd "php-${PHP_VERSION}"
# 飞腾ARM64编译优化标志
export CFLAGS="-O2 -march=armv8-a+simd -funroll-loops -fomit-frame-pointer"
export CXXFLAGS="$CFLAGS"
export LDFLAGS="-Wl,-O1"
log_info "开始configure配置..."
./configure \
--prefix="$INSTALL_DIR" \
--with-config-file-path="${INSTALL_DIR}/etc" \
--with-config-file-scan-dir="${INSTALL_DIR}/etc/php.d" \
--with-libdir=lib64 \
--enable-fpm \
--with-fpm-user="$PHP_USER" \
--with-fpm-group="$PHP_USER" \
--enable-opcache \
--enable-mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-mysqli=mysqlnd \
--with-openssl \
--with-curl \
--with-zlib \
--enable-mbstring \
--enable-bcmath \
--enable-gd \
--with-jpeg \
--with-zip \
--enable-soap \
--enable-xml \
--enable-intl \
--enable-sockets \
--enable-pcntl \
--enable-posix \
--with-sodium \
--with-gmp \
--with-readline \
--enable-calendar \
2>&1 | tee "${BUILD_DIR}/configure.log"
log_info "开始编译(${CORES}核并行)..."
make -j"$CORES" 2>&1 | tee "${BUILD_DIR}/make.log"
if grep -qE "^make.*Error" "${BUILD_DIR}/make.log"; then
log_error "编译失败,请检查 ${BUILD_DIR}/make.log"
exit 1
fi
log_info "安装PHP..."
make install
# 创建用户
if ! id "$PHP_USER" &>/dev/null; then
groupadd "$PHP_USER"
useradd -g "$PHP_USER" -s /sbin/nologin -M "$PHP_USER"
fi
# 配置文件
cp "${BUILD_DIR}/php-${PHP_VERSION}/php.ini-production" "${INSTALL_DIR}/etc/php.ini"
mkdir -p "${INSTALL_DIR}/etc/php.d" /var/log/php /var/run/php-fpm
cp "${INSTALL_DIR}/etc/php-fpm.conf.default" "${INSTALL_DIR}/etc/php-fpm.conf"
cp "${INSTALL_DIR}/etc/php-fpm.d/www.conf.default" "${INSTALL_DIR}/etc/php-fpm.d/www.conf"
# 写入飞腾优化配置
cat > "${INSTALL_DIR}/etc/php.d/phytium-optimize.ini" << 'INIEOF'
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
opcache.save_comments=1
opcache.jit=tracing
opcache.jit_buffer_size=128M
opcache.huge_code_pages=1
opcache.file_cache=/tmp/php-opcache
memory_limit=512M
date.timezone=Asia/Shanghai
INIEOF
# 创建opcache文件缓存目录
mkdir -p /tmp/php-opcache
chown www:www /tmp/php-opcache
# 环境变量
if ! grep -q "${INSTALL_DIR}/bin" /etc/profile; then
echo "export PATH=${INSTALL_DIR}/bin:${INSTALL_DIR}/sbin:\$PATH" >> /etc/profile
fi
log_info "==========================================="
log_info "飞腾FT系列 PHP ${PHP_VERSION} 安装完成!"
log_info ""
log_info "执行以下命令使环境变量生效:"
log_info " source /etc/profile"
log_info ""
log_info "启动NUMA优化的PHP-FPM:"
log_info " numactl --cpunodebind=0,1 --membind=0,1 \\"
log_info " ${INSTALL_DIR}/sbin/php-fpm"
log_info ""
log_info "验证安装:"
log_info " php -v && php -m | grep opcache"
log_info "==========================================="
---
十四、飞腾 vs 龙芯 配置对比速查
┌───────────────┬──────────────────────────────┬────────────────────────────────┐
│ 配置项 │ 飞腾FT (ARM64) │ 龙芯 (LoongArch) │
├───────────────┼──────────────────────────────┼────────────────────────────────┤
│ JIT │ 可以开启 opcache.jit=tracing │ 必须禁用 --disable-opcache-jit │
├───────────────┼──────────────────────────────┼────────────────────────────────┤
│ CFLAGS │ -march=armv8-a+simd │ 无特殊优化标志 │
├───────────────┼──────────────────────────────┼────────────────────────────────┤
│ NUMA调优 │ 必须做,FT2500有16个NUMA节点 │ 一般不需要 │
├───────────────┼──────────────────────────────┼────────────────────────────────┤
│ config.guess │ 系统自带支持aarch64 │ 必须手动更新 │
├───────────────┼──────────────────────────────┼────────────────────────────────┤
│ 大页 │ 支持,效果明显 │ 支持 │
├───────────────┼──────────────────────────────┼────────────────────────────────┤
│ Swoole │ 原生支持aarch64协程(v5.x) │ 需要v5.0.3+ │
├───────────────┼──────────────────────────────┼────────────────────────────────┤
│ PHP-FPM进程数 │ 可开到256+(多核优势) │ 保守一些 │
├───────────────┼──────────────────────────────┼────────────────────────────────┤
│ 性能短板 │ 跨NUMA内存访问(绑核解决) │ 单核性能偏弱 │
└───────────────┴──────────────────────────────┴────────────────────────────────┘
---
十五、常见问题排查
# 问题1:JIT开启后Segfault崩溃
# 原因:内存不足或JIT buffer太大
# 解决:
opcache.jit_buffer_size=64M # 先减小,逐步加大
# 问题2:PHP-FPM进程CPU占用高但QPS低
# 原因:跨NUMA内存访问(飞腾最常见问题)
# 解决:
numastat -p $(pgrep php-fpm | head -1) # 查看NUMA命中率
# 如果miss很高,执行绑核
# 问题3:OPcache文件缓存报Permission Denied
# 原因:文件缓存目录权限问题
chown -R www:www /tmp/php-opcache
# 问题4:编译时找不到库文件
# 原因:aarch64库路径可能在lib64下
export PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig:$PKG_CONFIG_PATH
# 问题5:Swoole协程报错
# 原因:旧版Swoole不支持aarch64汇编上下文
# 解决:升级Swoole到5.x版本
php --ri swoole | grep version
---
总结:飞腾PHP调优核心三板斧
第一斧:开启JIT(飞腾ARM64原生支持)
opcache.jit=tracing
opcache.jit_buffer_size=128M
→ CPU密集型任务提升30-100%
第二斧:NUMA绑核(飞腾特有杀手锏)
numactl --cpunodebind=0,1 --membind=0,1 php-fpm
→ QPS提升最高4倍,这是最大的性能杠杆
第三斧:大页+预加载(锦上添花)
opcache.huge_code_pages=1
opcache.preload=/path/to/preload.php
→ 减少TLB缺失,消除冷启动延迟
更多推荐


所有评论(0)