昨天在 v2ex 分享了一下 PHP7.3+Swoole4.4 / Go1.13 / MixPHP2.2 / Beego1.12 性能比照 被很多网友质疑,本不想引起争端,但一时冲动和网友打赌了 10 块钱。
质疑的点
本次次要质疑的是:
- 测试没有数据库查问 :大家感觉加上 db 查问会很不一样,然而我认为基准测试 hello world 代表天花板,还是有一些意义的,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 <coder.keda@gmail.com>
*/
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 2>&1 &
- 过程
[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
批改执行模式
有网友评论:beego dev 模式性能会差一些,于是从新测试
- 批改执行模式为
prod
测试发现 prod
比 dev
性能高大略 2666
Requests/sec
[nobody@tmp]$ cat conf/app.conf
appname = hello
httpport = 8989
runmode = prod
- 测试后果
[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 453.55us 427.00us 29.69ms 93.22%
Req/Sec 4.77k 328.51 5.70k 82.71%
2279372 requests in 2.00m, 299.98MB read
Requests/sec: 18993.39
Transfer/sec: 2.50MB
为防止不同工夫的测试数据浮动,同时也再测试一下 MixPHP
[nobody@tmp]$ 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 821.18us 347.98us 20.65ms 89.92%
Req/Sec 2.47k 227.03 5.80k 81.13%
1181243 requests in 2.00m, 212.91MB read
Requests/sec: 9835.54
Transfer/sec: 1.77MB
移除序列化,只测试数据库
有网友评论:PHP 的 json_encode 可能是性能差的起因,于是从新测试
- MixPHP
代码批改
<?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 <coder.keda@gmail.com>
*/
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 = 'hello, world!'; // 不序列化
return ResponseHelper::html($response, $content);
}
}
测试后果
[nobody@tmp]$ 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 819.22us 309.68us 23.65ms 87.91%
Req/Sec 2.47k 221.66 3.07k 76.21%
1179327 requests in 2.00m, 203.57MB read
Requests/sec: 9827.51
Transfer/sec: 1.70MB
- Beego
代码批改
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 := []byte("hello, world!") // 不序列化
c.Ctx.Output.Body(js)
}
func main() {runtime.GOMAXPROCS(1) // 限度应用线程数
beego.Router("/index", &IndexController{}, "*:Index")
beego.Run()}
测试后果
[nobody@tmp]$ 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 436.00us 363.84us 24.06ms 92.74%
Req/Sec 4.94k 319.79 5.99k 79.62%
2358720 requests in 2.00m, 292.43MB read
Requests/sec: 19652.80
Transfer/sec: 2.44MB
总结一下
测试后果 mix 比 beego 数据库查问 + 序列化的综合性能要低 38.3%
,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% | 16306.15~16327.19 |
- 开启 beego prod 模式
更换模式后 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 |