昨天在 V2EX 分享了一下 PHP7.3+Swoole4.4 / Go1.13 / MixPHP2.2 / Beego1.12 性能对比 被很多朋友质疑,本不想引起争端,但一时冲动和网友打赌了 10 块钱。
质疑的点
本次主要质疑的是:
- 测试没有数据库查询:大家觉得加上 db 查询会很不一样,但是我认为:基准测试代表天花板,还是有一些意义的,db 查询我也认为 mix 与 beego 应该是性能趋同的,我现在还没开始测试,等下看结果。
- 测试没有序列化:本次测试,我也加上 json 序列化。
- ab 测试不适合高并发测试:这一点我详细列举很多举例,试图说明同样的环境下,不同的压力,强弱的数值会变,但结果是不变的,这基本属于物理规则,说服不了那我就本次采用 wrk 测试吧。
当然测试没办法做到条件绝对一致的,但结果还是可以参考的
环境
硬件
- CPU: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz
- CPU(s): 12
- Mem: 15G
- Linux version 3.10.0-957.10.1.el7.x86_64
数据库:
- 本机
测试命令
wrk -d 120 -t 4 http://127.0.0.1:*/ 连接池
- 最大闲置:5
- 最大连接:50
线程数
- 为了最大化公平,本次两个框架都采用
1个线程测试
MixPHP 2.2
代码:为了公平,我把配置里的默认中间件都移除了,之前测试没有移除。
<?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 - CPU 状态:稳定在
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 Beego 1.12
代码:使用 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 - CPU 状态:稳定在
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 |
