首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >FrankenPHP 经典模式是否比 PHP-FPM 更快、更具扩展性

FrankenPHP 经典模式是否比 PHP-FPM 更快、更具扩展性

作者头像
Tinywan
发布2025-10-20 17:16:33
发布2025-10-20 17:16:33
10000
代码可运行
举报
文章被收录于专栏:开源技术小栈开源技术小栈
运行总次数:0
代码可运行

概述

FrankenPHP自称是 “现代PHP应用服务器”,提供了一种单进程的PHP运行解决方案。其工作模式(Worker Mode)通过减少框架初始化时间,显著提升了兼容应用的性能。

然而,并非所有应用都适合工作模式。由于应用中可能存在大量全局状态,适配工作模式并非总是简单。为了全面评估,我们将探讨FrankenPHP在“经典模式”下是否也能提升应用的性能。

在本文中,旨在验证这些结果,明确测试PHP运行时的性能,而非PHP脚本执行、Linux调度器、Web服务器或其他外部因素的影响。测试结果表明,PHP-FPM与FrankenPHP经典模式在性能和吞吐量上几乎没有差异。

测试环境设置

与我们之前比较不同PHP版本性能的文章一致,我们使用了一台Hetzner VPS,配备8个专用vCore(AMD EPYC 7003或9004,Hetzner CCX33)。操作系统为新发布的Debian 13(“Trixie”)。

我们将对比FrankenPHP v1.9.1PHP 8.4.12Caddy v2.10.2)与nginx/1.26.3搭配PHP-FPM 8.4.11的性能。测试工具为Vegeta v12.12.0

FrankenPHP通过推荐的curl | sh命令安装为独立二进制文件。nginx和PHP-FPM则通过Debian Trixie的官方软件源安装。

安装后,我们仅对nginx配置做小幅调整,修改端口以避免冲突,并启用Debian提供的PHP配置块。此时,FrankenPHP与nginx+PHP-FPM组合均使用默认配置,未进行性能优化。

为聚焦运行时环境的开销,而非PHP本身的性能,我们使用不含业务逻辑的简单脚本进行测试。此外,我们避免高并发测试,仅为每个CPU核心分配1个工作进程。完整的Vegeta输出(包括更多吞吐量和响应时间百分位数据)可通过下表中的“测试标签”链接查看。

测试HTML响应生成

一个典型的服务器端渲染HTML登陆页面大约包含50 KiB数据,我们以此作为基本测试场景:

代码语言:javascript
代码运行次数:0
运行
复制
<?php

header('content-type: text/html; charset=utf-8');

$str = str_repeat('x', 1023) . "\n";

for ($i = 0; $i < 50; $i++) {
 echo $str;
}

响应类型

FPM RPS

FrankenPHP经典模式 RPS

FPM 99% ms

FrankenPHP经典模式 99% ms

HTML

7023.11

6934.06

2.022

2.06

在60秒的测试中,8个客户端以最大速度请求服务器,nginx+FPM组合每秒处理7023个请求(整体延迟更优),而FrankenPHP经典模式处理6934个请求(最大延迟略优)。nginx+FPM比FrankenPHP经典模式快约1.3%,但差异不足以影响实际应用。

这就完结了吗?还没。登陆页面只是应用中的一种场景。如果其他场景的结果不同呢?

测试二进制响应生成

我们将响应改为二进制格式,例如PDF,测试结果如下:

响应类型

FPM RPS

FrankenPHP经典模式 RPS

FPM 99% ms

FrankenPHP经典模式 99% ms

HTML

7023.11

6934.06

2.022

2.06

PDF

7610.31

5368.85

1.828

4.246

仅将Content-Typetext/html改为application/pdf,保持响应内容不变,FPM的性能提升(延迟更优),而FrankenPHP变慢。

代码语言:javascript
代码运行次数:0
运行
复制
<?php

header('content-type: application/pdf');

$str = str_repeat('x', 1023) . "\n";

for ($i = 0; $i < 50; $i++) {
 echo $str;
}

接下来,我们测试在HTML中嵌入“加密”的Base64编码随机数据(通过随机数据模拟加密):

代码语言:javascript
代码运行次数:0
运行
复制
<?php

$random = new \Random\Randomizer(new \Random\Engine\Xoshiro256StarStar());
for ($i = 0; $i < 50; $i++) {
 echo $random->getBytesFromString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", 1023), "\n";
}

响应类型

FPM RPS

FrankenPHP经典模式 RPS

FPM 99% ms

FrankenPHP经典模式 99% ms

HTML

7023.11

6934.06

2.022

2.06

PDF

7610.31

5368.85

1.828

4.246

随机数据

1940.05

5606.22

7.704

3.143

FPM和FrankenPHP的性能均下降,这在意料之中,因为脚本执行了更多工作。但FrankenPHP的RPS是FPM的2.89倍,这一异常结果将在后文解释。

如果减少工作量,测试极简的“Hello World”呢?

代码语言:javascript
代码运行次数:0
运行
复制
<?php

echo "Hello World!";

响应类型

FPM RPS

FrankenPHP经典模式 RPS

FPM 99% ms

FrankenPHP经典模式 99% ms

HTML

7023.11

6934.06

2.022

2.06

PDF

7610.31

5368.85

1.828

4.246

随机数据

1940.05

5606.22

7.704

3.143

Hello World

18478.69

18403.81

0.904

0.877

FPM和FrankenPHP均达到约18400 RPS,差异仅0.4%,延迟表现相当。

高并发测试

Ivan Vulovic的文章测试了高并发场景。虽然我们认为这更多测量了操作系统调度器的性能,而非运行时本身,但FrankenPHP可能在调度器友好性上有所优化。我们以“Hello World”为例,测试高并发结果:

响应类型

FPM RPS

FrankenPHP经典模式 RPS

FPM 99% ms

FrankenPHP经典模式 99% ms

HTML

7023.11

6934.06

2.022

2.06

PDF

7610.31

5368.85

1.828

4.246

随机数据

1940.05

5606.22

7.704

3.143

Hello World

18478.69

18403.81

0.904

0.877

Hello World 并发100

21847.61

22675.24

9.742

23.365

FrankenPHP的RPS高出约3.7%,但延迟分布较差。

优化配置测试

上述测试均基于默认配置。我们尝试了一些性能优化:

  • FrankenPHP:官方性能优化文档仅建议“不要使用Musl”,而我们未使用Musl。
  • nginx和FPM
    • 禁用nginx访问日志(与FrankenPHP一致)。
    • 启用fastcgi_keep_conn
    • 设置FPM为pm=staticpm.max_children=16(与FrankenPHP的num_threads匹配)。

优化后,性能差异仍不明显。

输出压缩性能的影响

PDF和随机数据场景的性能差异如何解释?显然,我们测量的不是PHP-FPM与FrankenPHP的运行时开销,而是nginx和Caddy的输出压缩实现质量。

Vegeta设置了accept-encoding: gzip请求头,nginx和FrankenPHP会在适合的情况下自动压缩PHP响应:

是否压缩

FrankenPHP

nginx

HTML

PDF

随机数据

Hello World

在PDF场景中,两者均不压缩响应,nginx性能更优,而FrankenPHP处理较大响应体时表现不佳。在随机数据场景中,nginx尝试压缩不可压缩数据时性能下降,而FrankenPHP表现更好。

通过设置accept-encoding: identity禁用压缩,重新测试HTML响应:

响应类型

FPM RPS

FrankenPHP经典模式 RPS

FPM 99% ms

FrankenPHP经典模式 99% ms

HTML

7023.11

6934.06

2.022

2.06

PDF

7610.31

5368.85

1.828

4.246

随机数据

1940.05

5606.22

7.704

3.143

Hello World

18478.69

18403.81

0.904

0.877

Hello World 并发100

21847.61

22675.24

9.742

23.365

HTML 无GZIP

7456.47

5504.16

1.786

3.993

结果与PDF场景类似。我们还尝试用HAProxy 3.0.11替代nginx作为FastCGI网关,略微提升了RPS和延迟,但差异在实际应用中不显著。

结论

综上,PHP-FPM与FrankenPHP经典模式在运行时开销上的差异微乎其微,不足以推荐始终切换到FrankenPHP经典模式。

与之前的基准测试一致,应用架构对性能的影响最大,没有捷径能显著提升性能。优化PHP启动时间的微秒级差异,在面对数百毫秒的数据库等待时间时无足轻重。 使用Tideways等APM工具可帮助发现应用代码中的性能瓶颈。

关于选择PHP运行时,建议根据团队熟悉度和需求决定:

  1. 若已使用Caddy与PHP-FPM,切换到FrankenPHP可降低运维复杂性。
  2. 若需FrankenPHP独有功能(如103 Early Hints、Go扩展或Mercure实时支持),经典模式可能更合适。
  3. 若应用已优化但未适配工作模式,PHP-FPM仍略有性能优势。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-09-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开源技术小栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 测试环境设置
  • 测试HTML响应生成
  • 测试二进制响应生成
  • 高并发测试
  • 优化配置测试
  • 输出压缩性能的影响
  • 结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档