昨天在 V2EX 分享了一下 PHP7.3+Swoole4.4 / Go1.13 / MixPHP2.2 / Beego1.12 性能对比 被很多朋友质疑,本不想引起争端,但一时冲动和网友打赌了 10 块钱。
本次主要质疑的是:
当然测试没办法做到条件绝对一致的,但结果还是可以参考的
硬件
数据库:
测试命令
wrk -d 120 -t 4 http://127.0.0.1:*/
连接池
线程数
1
个线程测试代码:为了公平,我把配置里的默认中间件都移除了,之前测试没有移除。
<?php
namespace App\Web\Controllers;
use App\Common\Helpers\ResponseHelper;
use Mix\Http\Message\ServerRequest;
use Mix\Http\Message\Response;
/**
* Class IndexController
* @package App\Web\Controllers
* @author liu,jian <[email protected]>
*/
class IndexController
{
/**
* Index
* @param ServerRequest $request
* @param Response $response
* @return Response
*/
public function index(ServerRequest $request, Response $response)
{
/** @var Database $db */
$db = context()->get('database');
$result = $db->prepare('select * from test limit 1')->queryAll();
$content = json_encode($result);
return ResponseHelper::html($response, $content);
}
}
/usr/local/php-7.3.12/bin/php mix/bin/mix.php web -d
[nobody@~]$ ps -ef | grep mix.php
nobody 25972 1 0 18:36 ? 00:00:00 /usr/local/php-7.3.12/bin/php mix/bin/mix.php web -d
[nobody@~]$ curl http://127.0.0.1:9501/
[{"id":1,"name":"3"}]
9936.36 ~ 10080.25
左右[nobody@~]$ wrk -d 120 -t 4 http://127.0.0.1:9501/
Running 2m test @ http://127.0.0.1:9501/
4 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 806.18us 501.04us 51.95ms 97.58%
Req/Sec 2.53k 245.91 5.92k 79.28%
1210639 requests in 2.00m, 218.21MB read
Requests/sec: 10080.25
Transfer/sec: 1.82MB
99.3~99.7%
左右。 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
25972 nobody 20 0 1166992 12368 4064 R 99.7 0.1 2:41.11 php
代码:使用 runtime.GOMAXPROCS(1)
限制了线程数。
package main
import (
"encoding/json"
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql"
_ "hello/routers"
"runtime"
)
type Test struct {
Id int `orm:"column(id)"json:"id"`
Name string `orm:"column(name)"json:"name"`
}
func init() {
orm.RegisterModel(new(Test))
orm.RegisterDriver("mysql", orm.DRMySQL)
maxIdle := 5
maxConn := 50
orm.RegisterDataBase("default", "mysql", "*****@tcp(***:3306)/test?charset=utf8&loc=Asia%2FShanghai&parseTime=true", maxIdle, maxConn)
}
type IndexController struct {
beego.Controller
}
func (c *IndexController) Index() {
o := orm.NewOrm();
var row []*Test
o.Raw("select * from test limit 1").QueryRows(&row);
js, _ := json.Marshal(row)
c.Ctx.Output.Body(js)
}
func main() {
runtime.GOMAXPROCS(1) // 限制使用线程数
beego.Router("/index", &IndexController{}, "*:Index")
beego.Run()
}
为了不让日志影响到性能,屏蔽输出。
nohup ./gobeego_linux >> /dev/null 1>&2 &
[nobody@~]$ ps -ef| grep bee
nobody 27316 1 0 18:37 ? 00:00:00 ./gobeego_linux
[nobody@~]$ curl http://127.0.0.1:8989/index
[{"id":1,"name":"3"}]
16306.15 ~ 16327.19
左右[nobody@~]$ wrk -d 120 -t 4 http://127.0.0.1:8989/index
Running 2m test @ http://127.0.0.1:8989/index
4 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 521.18us 427.56us 29.46ms 92.23%
Req/Sec 4.10k 260.69 4.74k 79.96%
1959389 requests in 2.00m, 310.19MB read
Requests/sec: 16327.19
Transfer/sec: 2.58MB
99.7~100.3%
左右。 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
27316 nobody 20 0 114736 10660 5008 S 100.3 0.1 0:39.87 gobeego_linux
测试结果 mix 比 beego 数据库查询+序列化的综合性能要低 62%
,beego 更加优秀,不过 mix 动态脚本语言能做到这样也是蛮可以了(我只能这样安慰自己,但也是事实),显然我打赌输了,愿赌服输。
| 框架 | 线程数 | CPU | 数值 |
| PHP 7.3.12 + Swoole 4.4.14 + MixPHP 2.2 | 1 | 99.3~99.7% | 9936.36 ~ 10080.25 |
| Go 1.13.4 + Beego 1.12.1 | 1 | 99.7~100.3% | 16290.73 ~ 16327.19 |
测试结果 mix 比 beego 数据库查询+序列化的综合性能要低 38.3%,上面我写错了!
更换模式后 beego 性能得到了显著提升,测试结果 mix 比 beego 数据库查询+序列化的综合性能要低 48.2%
。
| 框架 | 线程数 | 数值 |
| ---- | ---- | ---- |
| PHP 7.3.12 + Swoole 4.4.14 + MixPHP 2.2 | 1 | 9835.54 |
| Go 1.13.4 + Beego 1.12.1 | 1 | 18993.39 |
移除序列化后测试结果变化非常小,说明序列化在这个测试中影响很小,也就是序列化相对于 db 查询来说,对整体性能影响比我们想象的要小很多。
| 框架 | 线程数 | 数值 |
| ---- | ---- | ---- |
| PHP 7.3.12 + Swoole 4.4.14 + MixPHP 2.2 | 1 | 9827.51 |
| Go 1.13.4 + Beego 1.12.1 | 1 | 19652.80 |
V2EX 没办法修改内容,完整的测试报告在这里:
1
luozic 2020-07-25 19:46:29 +08:00 via iPhone
同一机器玩都没达到各自的最佳,最好搞分开的 client server
|
2
sky101001 2020-07-25 21:36:40 +08:00
赞一个楼主的实证精神
|
3
linxl 2020-07-25 22:02:51 +08:00
为啥会有这样的差距?
|
4
wei193 2020-07-25 23:18:15 +08:00 via Android
如果没有记错,beego 还有一个运行模式,好像 prod 和 dev 性能也有蛮大的差异。不知道楼主用的是啥模式
|
5
onanying OP @luozic 分开又会有新的问题,网络吞吐量成为瓶颈,网络的其他软件占用局域网带宽,测试的结果就更加不准确了,只能现在这样了,条件不允许。
|
6
HiCode 2020-07-26 02:48:08 +08:00
为楼主点赞!
|
7
noqwerty 2020-07-26 03:44:11 +08:00 via Android
愿赌服输,挺好的,虽然大家都说这种框架的 benchmark 没啥意义,但是每次都忍不住看一下😂
|
8
loading 2020-07-26 05:58:27 +08:00 via Android
赞楼主精神
|
9
mind3x 2020-07-26 14:11:26 +08:00
你这个 benchmark 看起来 cpu 主要花在 json 序列化上,php 的 json_encode 是 C 写的,按理说不应该差这么多。
我怀疑数据库连接池的行为或者数据库驱动有什么不同,建议拿掉 json 序列化再测一下。 |
10
ben1024 2020-07-27 09:10:33 +08:00
可以尝试下
控制下变量,单次只测试一点 还有应用预热 |
11
ben1024 2020-07-27 09:11:39 +08:00
SQL 查询还需要加个随机数,避免 SQL 缓存
|
12
onanying OP @wei193 更换模式后 beego 性能得到了显著提升,测试结果 mix 比 beego 数据库查询+序列化的综合性能要低 48.2%
|
13
onanying OP @mind3x 移除序列化后测试结果变化非常小,说明序列化在这个测试中影响很小,也就是序列化相对于 db 查询来说,对整体性能影响比我们想象的要小很多。我在帖子后面追加了相关测试,https://zhuanlan.zhihu.com/p/163700975 也有完整的测试细节
|
14
onanying OP @ben1024 正式使用环境也是有 sql 缓存的,这个感觉就没必要的,主要是看框架+语言直接,大概模拟一点真实业务场景,看看差异
|
15
mind3x 2020-07-27 15:24:41 +08:00
@onanying 所以综合你之前无数据库的 benchmark 结果,总的推论是 php 的 MySQL 驱动或者连接池性能要比 go 的差不少。
|
16
onanying OP @mind3x 推论是对的,php 驱动是 pdo,是 c 写的,应该性能不会差,可能差距在 (基于 Swoole Channel 实现的连接池,pdo 支持协程是使用的 Hook 技术)和 (php 没有 jit,代码越多总执行时间差距越大) 这两方面
|
17
tinzing 2020-08-14 17:43:05 +08:00
其它 PHP 框架差距呢,譬如 TP,
|