尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
FrameworkBenchmarks 中的 PHP 基准测试指南:FPM/FastCGI 架构、ORM 对比与性能调优
性能测试测试后端开发者工具【免费下载链接】FrameworkBenchmarksSource for the TechEmpower Framework Benchmarks project项目地址https://gitcode.com/gh_mirrors/fr/FrameworkBenchmarks点击查看免费下载导读本文基于 frameworks/PHP/php/README.md 展开系统讲解 TechEmpower Framework Benchmarks 项目中 PHP 基准测试的完整技术栈从 PHP 8.x OPcache 与 php-fpm/FastCGI 的运行环境到 nginx、h2o、Caddy/FrankenPHP、Workerman 等多种 Web 服务器形态再到 PHP-PDO 原生实现、PHP ActiveRecord、Eloquent ORM 与 Laravel Query Builder 四层 ORM 方案的对比。读完本文你将掌握该基准目录下每个测试入口的实现细节、benchmark_config.json中十余种测试变体的含义以及仓库中真实使用的 FPM 池、OPcache、JIT 与 FastCGI 调优参数可直接复用到自己的 PHP 性能优化实践中。一、项目定位PHP 在 FrameworkBenchmarks 中的角色TechEmpower Framework Benchmarks 是一个跨语言、跨框架的 Web 平台基准测试套件而frameworks/PHP/php目录承载的是其中PHP 原生平台classification: Platform、approach: Realistic的测试。从 benchmark_config.json 可以看到它通过一套共享的入口脚本json.php、plaintext.php、dbraw.php、dbquery.php、fortune.php、updateraw.php配合不同的 Web 服务器与运行形态组合出如下测试变体测试变体Web 服务器平台数据库说明defaultnginxFPM/FastCGIMySQL标准 Raw 实现raw7-tcpnginxFPM/FastCGIMySQL通过 TCP socket 与数据库通信pgsql-rawnginxFPM/FastCGIPostgres将 DSN 替换为 pgsqlh2oh2oFPM/FastCGIMySQL使用 h2o 作为 HTTP 服务器poolsnginxFPM/FastCGIMySQL启用多个 php-fpm 池caddyCaddyFPM/FastCGIMySQL使用 Caddy 的php_fastcgifrankenCaddyFrankenPHPMySQL内置 PHP 的 FrankenPHPworkermannoneWorkermanMySQL常驻内存的 PHP 应用服务器eloquentnginxFPM/FastCGIMySQL完整 Eloquent ORMlaravel-query-buildernginxFPM/FastCGIMySQL仅 Query BuilderMicro ORM所有变体统一监听8080 端口数据库连接均指向tfb-database主机上的hello_world库用户名benchmarkdbuser、密码benchmarkdbpass。同一套入口脚本被多种服务器形态复用正是该基准的核心设计对比的重点是运行 PHP 的方式而不是业务代码差异。二、基础设施软件版本README 明确记录了基准测试运行的软件栈PHP 8.*并启用OPcache字节码缓存当前仓库的 Dockerfile 从ondrej/phpPPA 安装php8.5系列包详见 php.dockerfile。平台php-fpmFastCGI 进程管理器。Web 服务器nginx、h2o仓库中还有 Caddy、FrankenPHP 与 Workerman 变体。数据库MySQL 9 与 PostgreSQL 18。从 php.dockerfile 的启动命令可以还原真实运行链路FROM ubuntu:24.04 RUN apt-get install -yqq nginx git unzip \ php8.5 php8.5-common php8.5-cli php8.5-fpm php8.5-mysql COPY deploy/conf/* /etc/php/8.5/fpm/ ADD ./ /php RUN if [ $(nproc) 2 ]; then sed -i s|pm.max_children 1024|pm.max_children 512|g /etc/php/8.5/fpm/php-fpm.conf ; fi; EXPOSE 8080 CMD service php8.5-fpm start \ nginx -c /php/deploy/nginx7.conf -g daemon off;这里有两个值得注意的细节deploy/conf/*中自定义的 FPM 配置与php.ini会整体覆盖系统配置双核机器上pm.max_children会从 1024 自动降为 512避免进程数超过 CPU 核数导致上下文切换开销。注意README 中标注 PHP 为 8.*而benchmark_config.json中flavor字段仍写有 PHP8.1Dockerfile 已实际采用 php8.5 包以仓库当前 Dockerfile 的实际安装版本为准。三、测试入口脚本从源码看各测试类型的实现README 给出的测试 URL 全部映射到仓库根目录下的原生 PHP 脚本。下面结合源码逐一解读文件均在frameworks/PHP/php/下。JSON 序列化测试/json.phpjson.php 是全仓库最简的实现仅两行header(Content-Type: application/json); echo json_encode([message Hello, World!]);它用 PHP 标准库json_encode输出{message:Hello, World!}用于衡量框架本身在零业务逻辑下的序列化开销。数据库单行查询Raw/dbraw.phpdbraw.php 是 Raw 实现的 DB 测试代表核心特征$pdo new PDO(mysql:hosttfb-database;dbnamehello_world, benchmarkdbuser, benchmarkdbpass, [ PDO::ATTR_PERSISTENT true ]); $statement $pdo-query(SELECT id,randomNumber FROM World WHERE id . mt_rand(1, 10000)); echo json_encode($statement-fetch(PDO::FETCH_ASSOC), JSON_NUMERIC_CHECK);使用PDO 持久连接PDO::ATTR_PERSISTENT连接复用贯穿整个进程生命周期主键在1~10000间随机查询结果以JSON_NUMERIC_CHECK输出保证数字字段不被转成字符串。多行变量查询Raw/dbquery.php?queriesdbquery.php 是变量查询测试的核心展示了参数读取与上限控制$query_count 1; if ((int) $_GET[queries] 1) { $query_count min($_GET[queries], 500); } $statement $pdo-prepare(SELECT id,randomNumber FROM World WHERE id ?); while ($query_count--) { $statement-execute([mt_rand(1, 10000)]); $arr[] $statement-fetch(PDO::FETCH_ASSOC); } echo json_encode($arr, JSON_NUMERIC_CHECK);两个关键约定贯穿所有带?queries的脚本未传参时默认执行 1 次最大值被钳制在 500同时这里改用预处理语句 参数绑定与dbraw.php的字符串拼接形成对比。更新测试/updateraw.php?queriesupdateraw.php 演示了读写混合事务$pdo new PDO(..., [ PDO::ATTR_PERSISTENT true, PDO::ATTR_DEFAULT_FETCH_MODE PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES false, // 使用服务端预处理 ]); $statement $pdo-prepare(SELECT id,randomNumber FROM World WHERE id?); $updateStatement $pdo-prepare(UPDATE World SET randomNumber? WHERE id?); while ($query_count--) { $id mt_rand(1, 10000); $statement-execute([$id]); $world $statement-fetch(); $updateStatement-execute([$world[randomNumber] mt_rand(1, 10000), $id]); $arr[] $world; } echo json_encode($arr, JSON_NUMERIC_CHECK);它额外关闭了PDO::ATTR_EMULATE_PREPARES强制走 MySQL 服务端预处理协议是 PDO 层常见的性能与安全调优点。Fortune 模板测试/fortune.phpfortune.php 是唯一返回 HTML 的测试$arr $pdo-query(SELECT id, message FROM Fortune)-fetchAll(PDO::FETCH_KEY_PAIR); $arr[0] Additional fortune added at request time.; asort($arr); // ... 输出 table并针对每个值调用 htmlspecialchars($fortune, ENT_QUOTES, UTF-8)它要求先取出全部Fortune行、追加一条额外数据、按 message 排序再以 HTML 表格输出且所有动态内容必须经过htmlspecialchars转义——这是对输出渲染安全性的标准检验。Plaintext 测试/plaintext.phpplaintext.php 与 JSON 测试一样极简header(Content-Type: text/plain); echo Hello, World!;四、ORM 对比ActiveRecord、Eloquent 与 Laravel Query BuilderREADME 花了大量篇幅说明这套目录刻意对比了四种数据访问层PHP-PDO Raw最底层的基准衡量零抽象开销PHP ActiveRecord基于php-activerecord的轻量 ORMLaravel Query Builderilluminate/database的查询构造器独立于 Laravel 框架运行用于测量依赖注入容器Capsule与查询构造器的开销Eloquent ORM在 Query Builder 之上叠加 ORM 模型用于测量模型层的增量开销。README 明确指出php-eloquent与php-laravel-query-builder这两个测试可以通过Capsule 独立运行不必依赖完整的 Laravel 框架将它们的成绩与 Laravel 框架自身的结果对比还能看出Laravel 前端组件相对后端组件的开销。4.1 Eloquent ORM 实现eloquent/init-capsule.php 用 Capsule 独立装配数据库连接$capsule new Capsule; $capsule-addConnection([ driver mysql, host tfb-database, database hello_world, username benchmarkdbuser, password benchmarkdbpass, options [PDO::ATTR_PERSISTENT true], ]); $capsule-setAsGlobal();eloquent/boot-eloquent.php 定义World模型并启动 Eloquentclass World extends \Illuminate\Database\Eloquent\Model { protected $table World; public $timestamps false; } $capsule-bootEloquent();eloquent/db-eloquent.phpWorld::find(mt_rand(1, 10000))单模型查询 / 循环查询eloquent/update-eloquent.phpWorld::find($id)→ 改randomNumber→$world-save()eloquent/fortune-eloquent.php定义Fortune模型Fortune::all()后追加数据并按 message 排序。模型关闭了timestamps不维护created_at/updated_at这是基准场景下避免无效写入的标准做法。4.2 Laravel Query Builder 实现eloquent/db-laravel-query-builder.php 只依赖init-capsule.php不加载 Eloquent 模型Capsule::table(World)-where(id, mt_rand(1, 10000))-get()-first()它测量的正是 README 所说的依赖注入容器 查询构造器、不含 ORM 模型的中间层开销。benchmark_config.json中该变体标记为orm: Micro而eloquent标记为orm: Full。4.3 PHP ActiveRecordREADME 记录了PHP ActiveRecord Nightly 20121221。仓库中的 models/World.php 正是 ActiveRecord 模型class World extends ActiveRecord\Model { static $table_name World; }README 中对应的 ORM 测试入口为/dborm.php与/dborm.php?queries5不过从当前仓库目录结构看实际保留并持续维护的是 Raw 实现dbraw.php/dbquery.php/updateraw.php/fortune.php与 Eloquent 实现eloquent/子目录benchmark_config.json也仅注册了这两类入口。五、Web 服务器与 FastCGI 部署形态5.1 nginx php-fpm默认与 pools 变体deploy/nginx7.conf 是默认形态的核心配置集中了一批针对 FastCGI 与长连接的调优项upstream fastcgi_backend { server unix:/var/run/php/php-fpm.sock; keepalive 36; # 复用 FastCGI 上游连接 } server { listen 8080 reuseport; # 多进程共享同一端口 root /php/; location ~ \.php$ { fastcgi_pass fastcgi_backend; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include /etc/nginx/fastcgi_params; } }其他要点worker_processes autoworker_cpu_affinity auto、pcre_jit on、fastcgi_keep_conn onFastCGI 连接保持、fastcgi_buffers 256 16k、access_log off、server_tokens off。pools变体则使用 deploy/conf/php-fpm-pools.conf启动www与www2两个静态池各 512 子进程分别监听php-fpm.sock与php-fpm-2.sock用于检验多池隔离下的表现。FPM 侧对应 deploy/conf/php-fpm.conf采用pm static固定子进程模型pm static pm.max_children 1024 ; 双核机器构建时会被 sed 替换为 512 listen /run/php/php-fpm.sock listen.backlog -1 ; 由内核决定 backlog rlimit_files 1000000 error_log /dev/stderr5.2 h2o php-fpmdeploy/h2o.conf 展示了 h2o 通过 FastCGI 协议转发 PHP 的极简写法server-name: h2o max-connections: 65536 listen: port: 8080 hosts: default: paths: /: file.dir: /var/www file.custom-handler: extension: .php fastcgi.timeout.keepalive: 3900 fastcgi.connect: port: /var/run/php/php-fpm.sock type: unixphp-h2o.dockerfile 会在构建阶段从源码编译 h2o并在容器启动时执行sed -i s/num-threads: x/num-threads: $((2 * $(nproc)))/g /opt/h2o/etc/h2o.conf service php8.5-fpm start /opt/h2o/bin/h2o -c /opt/h2o/etc/h2o.conf即按 CPU 核数的两倍动态设置 h2o 线程数。5.3 Caddy 与 FrankenPHPdeploy/caddy/Caddyfile 仅三行通过 Caddy 的php_fastcgi指令对接 FPM:8080 { root * /php php_fastcgi unix//var/run/php/php-fpm.sock }而franken变体php-franken.dockerfile基于dunglas/frankenphp:php8.5由 FrankenPHP 直接把 PHP 运行时内嵌进 Caddy无需独立 FPM 进程这也是它platform: Frankenphp、webserver: caddy分类的由来。5.4 Workerman无外部 Web 服务器workerman变体php-workerman.dockerfile、deploy/workerman/start.php通过Adapterman Workerman让传统 PHP 脚本常驻内存运行$web new Worker(http://0.0.0.0:8080); $web-count (int) shell_exec(nproc) * 4; $web-reusePort true; $web-onMessage static function ($connection) { $file realpath(WEBROOT . $path); if (false $file || !str_ends_with($file, .php)) { /* 404 */ } if (!str_starts_with($file, WEBROOT)) { /* 400 */ } header(Header::$date); $connection-send(exec_php_file($file)); };exec_php_file通过ob_start()捕获脚本输出后返回配合 deploy/workerman/cli-php.ini其中opcache.enable_cli1实现 CLI 下的 OPcache JIT 加速。六、OPcache 与 JITPHP 性能调优的仓库级依据README 明确声明测试运行在PHP 8.* OPcache之上。仓库内 deploy/conf/php.ini 的[opcache]段给出了完整的基准级配置逐项含义如下配置项仓库取值作用opcache.enable1启用 Zend OPcacheopcache.validate_timestamps0关闭文件时间戳校验脚本变更需手动重置 OPcache 或重启服务换取零校验开销opcache.save_comments0丢弃 PHPDoc 注释减小缓存体积opcache.enable_file_override1让file_exists()等文件操作直接命中缓存opcache.huge_code_pages1将 PHP 代码段放入 Huge Pages减少 TLB 缺失opcache.jittracing启用跟踪型 JITopcache.jit_buffer_size128MJIT 缓冲上限同时该文件还做了生产环境常规收敛display_errors Off、log_errors On、variables_order GPCS、register_argc_argv Off、expose_php Off、realpath_cache_size 4096k、realpath_cache_ttl 600等都是在削减不必要的运行时开销。七、PostgreSQL 变体与配置替换技巧pgsql-raw变体的实现方式颇具代表性php-pgsql-raw.dockerfile 不维护第二套业务代码而是安装php8.5-pgsql后在构建期用sed把四个脚本中的 DSN 前缀整体替换RUN sed -i s|PDO(mysql:|PDO(pgsql:|g dbraw.php RUN sed -i s|PDO(mysql:|PDO(pgsql:|g dbquery.php RUN sed -i s|PDO(mysql:|PDO(pgsql:|g fortune.php RUN sed -i s|PDO(mysql:|PDO(pgsql:|g updateraw.php这解释了为什么benchmark_config.json中pgsql-raw与default的 URL 完全一致仅database: Postgres不同——同一份 Raw 代码通过 DSN 替换即可切换数据库。八、维护注意事项与测试入口速查README 特别提醒了一个仓库维护细节编辑本目录时必须强制提交变更文件git add -f因为测试运行过程中会有部分文件被程序触碰写入从而被.gitignore覆盖。将 README 中的测试 URL 整理成速查表方便按类型验证本地环境测试类型Raw 入口Eloquent / Query Builder 入口JSON 编码http://localhost/json.php—数据库单行映射http://localhost/dbraw.phphttp://localhost/eloquent/db-eloquent.php变量查询http://localhost/dbraw.php?queries5http://localhost/eloquent/db-eloquent.php?queries5更新测试http://localhost/updateraw.php?queries5http://localhost/eloquent/update-eloquent.php?queries5Fortunehttp://localhost/fortune.phphttp://localhost/eloquent/fortune-eloquent.phpPlaintexthttp://localhost/plaintext.php—Query Builder—http://localhost/eloquent/db-laravel-query-builder.php?queries5README 另记录了 ActiveRecord 的 ORM 入口http://localhost/dborm.php如前文所述当前仓库实际保留的为 Raw 与eloquent/目录下的实现。结语frameworks/PHP/php目录是理解PHP 在现代 Web 基准中如何被评估的浓缩样本一套 PDO 原生脚本同时被 nginx、h2o、Caddy、FrankenPHP、Workerman 五种运行形态复用叠加 PHP ActiveRecord、Eloquent、Laravel Query Builder 三种 ORM 分层再配合 OPcache/JIT 与 FPM 静态池的激进调优。无论你是想复现基准结果、对比 ORM 开销还是为自己的 PHP 服务做 FastCGI 与 OPcache 层面的性能收敛仓库中的 benchmark_config.json、deploy/nginx7.conf、deploy/conf/php-fpm.conf 与 deploy/conf/php.ini 都是可直接借鉴的配置蓝本。赞分享性能测试测试后端开发者工具【免费下载链接】FrameworkBenchmarksSource for the TechEmpower Framework Benchmarks project项目地址https://gitcode.com/gh_mirrors/fr/FrameworkBenchmarks点击查看免费下载相关推荐PHP Fat-Free Framework 基准测试实战TechEmpower FrameworkBenchmarks 中的路由、ORM 与 FPM 部署剖析PHP Fat Free Framework 基准测试实战TechEmpower FrameworkBenchmarks 中的路由、ORM 与 FPM 部署剖性能测试测试后端开发者工具KumbiaPHP 在 TechEmpower FrameworkBenchmarks 中的基准测试实现与性能调优指南KumbiaPHP 在 TechEmpower FrameworkBenchmarks 中的基准测试实现与性能调优指南 KumbiaPHP 是一个基于 PHP性能测试测试后端开发者工具gz-sim 性能基准测试指南构建、运行、对比与调优gz sim 性能基准测试指南构建、运行、对比与调优 gazebo 最新版 gz simGazebo Sim在仓库的 test/benchmark 目录下机器人上一篇slideout代码覆盖率分析提升测试质量的方法下一篇Decepticon 联系/通信计划生成器contact-template为自主 AI 红队演练设计联系人、升级链与中止通知机制创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

Playwright多线程并发内存CPU消耗优化:从原理到落地的完整方案

Playwright多线程并发内存CPU消耗优化:从原理到落地的完整方案

做Web自动化的人应该都有这种感觉:脚本单线程跑的时候一切正常,一旦开多线程上并发,内存曲线就像坐了火箭,CPU也跟着一路狂飙。Playwright的并发资源消耗问题,我前前后后调了两三周,从盲目的“加线程数”到…

📅 2026/10/15 20:30:22
Git City: Pulse VS Code 扩展完整演进解析——从点亮建筑到全维度编码活动追踪

Git City: Pulse VS Code 扩展完整演进解析——从点亮建筑到全维度编码活动追踪

前端数据可视化3D渲染 【免费下载链接】git-city Your GitHub profile as a 3D pixel art building in an interactive city 项目地址: https://gitcode.com/gh_mirrors/gi/git-city 点击查看 免费下载 Git City(git-city)是一个把 GitHub 个…

📅 2026/10/15 20:30:22
边缘-云协同架构下低延迟数据传输优化实践

边缘-云协同架构下低延迟数据传输优化实践

我们团队在推进模拟项目X的过程中,面临过一个很现实的性能瓶颈:边缘端的数据要全部汇聚到云端处理,再决定是否下发控制指令。当节点数量从几十扩展到几百,链路波动、带宽占用、决策时延这些老问题全部被放大。后来我们花了大概三个…

📅 2026/10/15 20:25:20
MORE NEWS

更多资讯

📰

硬盘突然爆满怎么办?一套安全清理与瘦身实操指南

你点开这篇,多半是电脑或手机最近突然红了盘、只剩几个G,或者看着磁盘空间一天比一天少,也不知道该从哪里下手。硬盘爆满这事儿不新鲜,但每次看到进度条全红,还是让人头皮发麻。我这些年处理过不少类似的求助&#xff…

📰

智能驾驶基础理论全解析:从感知到控制的系统框架与工程实践

1. 从“会开”到“开得明白”:智能驾驶基础理论到底在解决什么问题很多人第一次接触智能驾驶,脑子里冒出来的画面是激光雷达转圈、摄像头识别人脸、车子自己打方向盘。但真到动手做项目或者面试被追问的时候,才发现真正卡住自己的不是某个算法…

📰

基于微信小程序的研究生之路:任务、文献与打卡全栈开发实战

最近在准备毕业设计的朋友,或者正在被研究生阶段各种任务、进度和节点折磨的同学,多少都会对"研究生之路"这个选题产生条件反射般的兴趣。它听上去不像一个冷冰冰的系统,而更像一个学习伙伴。实际上,这个小程序要做的正…

📰

毕业论文写作AI辅助实操指南:人机协作的正确边界

每年三四月份,应届生们就会集体陷入一种名为“毕业论文”的焦虑。定题没方向、综述没头绪、写了删删了写,总有人深夜对着空白文档怀疑人生。这两年我陆续试了不少写作辅助工具,其中书匠策AI算是我个人觉得在毕业论文这个场景里比较“对症”的…

📰

Linux串口数据采集实战:从读取、解析到稳定存储的完整方案

1. 串口数据采集这件事,远比想象中要琐碎 串口通信在工业控制、传感器采集、嵌入式调试这些场景里,几乎是绕不开的一环。很多人第一次接触Linux下的串口编程,脑子里想的可能是"打开设备文件、读数据、写文件"三步走,代码…

📰

从跑工具到真正看懂漏洞:网络安全转行的进阶路线

很多人转行网络安全,都是从“跑工具”开始的。拿到扫描器,对着目标跑一遍,看到高危漏洞的图标跳出来,截图、复制描述、粘贴到报告里,整套流程好像就结束了。但做了半年、一年之后,你大概率会遇到一种很具体…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬