
昨天在 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 Q4h7388nR28s95fa 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, |