MixPHP 2.2 / Beego 1.12 数据库查询性能对比

2020-07-25 19:41:27 +08:00
 onanying

昨天在 V2EX 分享了一下 PHP7.3+Swoole4.4 / Go1.13 / MixPHP2.2 / Beego1.12 性能对比 被很多朋友质疑,本不想引起争端,但一时冲动和网友打赌了 10 块钱。

质疑的点

本次主要质疑的是:

当然测试没办法做到条件绝对一致的,但结果还是可以参考的

环境

硬件

数据库:

测试命令

wrk -d 120 -t 4 http://127.0.0.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"}]
[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
  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"}]
[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
  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 |

3089 次点击
所在节点    PHP
17 条回复
luozic
2020-07-25 19:46:29 +08:00
同一机器玩都没达到各自的最佳,最好搞分开的 client server
sky101001
2020-07-25 21:36:40 +08:00
赞一个楼主的实证精神
linxl
2020-07-25 22:02:51 +08:00
为啥会有这样的差距?
wei193
2020-07-25 23:18:15 +08:00
如果没有记错,beego 还有一个运行模式,好像 prod 和 dev 性能也有蛮大的差异。不知道楼主用的是啥模式
onanying
2020-07-25 23:35:43 +08:00
@luozic 分开又会有新的问题,网络吞吐量成为瓶颈,网络的其他软件占用局域网带宽,测试的结果就更加不准确了,只能现在这样了,条件不允许。
HiCode
2020-07-26 02:48:08 +08:00
为楼主点赞!
noqwerty
2020-07-26 03:44:11 +08:00
愿赌服输,挺好的,虽然大家都说这种框架的 benchmark 没啥意义,但是每次都忍不住看一下😂
loading
2020-07-26 05:58:27 +08:00
赞楼主精神
mind3x
2020-07-26 14:11:26 +08:00
你这个 benchmark 看起来 cpu 主要花在 json 序列化上,php 的 json_encode 是 C 写的,按理说不应该差这么多。

我怀疑数据库连接池的行为或者数据库驱动有什么不同,建议拿掉 json 序列化再测一下。
ben1024
2020-07-27 09:10:33 +08:00
可以尝试下
控制下变量,单次只测试一点
还有应用预热
ben1024
2020-07-27 09:11:39 +08:00
SQL 查询还需要加个随机数,避免 SQL 缓存
onanying
2020-07-27 11:40:27 +08:00
@wei193 更换模式后 beego 性能得到了显著提升,测试结果 mix 比 beego 数据库查询+序列化的综合性能要低 48.2%
onanying
2020-07-27 11:41:44 +08:00
@mind3x 移除序列化后测试结果变化非常小,说明序列化在这个测试中影响很小,也就是序列化相对于 db 查询来说,对整体性能影响比我们想象的要小很多。我在帖子后面追加了相关测试,https://zhuanlan.zhihu.com/p/163700975 也有完整的测试细节
onanying
2020-07-27 11:43:40 +08:00
@ben1024 正式使用环境也是有 sql 缓存的,这个感觉就没必要的,主要是看框架+语言直接,大概模拟一点真实业务场景,看看差异
mind3x
2020-07-27 15:24:41 +08:00
@onanying 所以综合你之前无数据库的 benchmark 结果,总的推论是 php 的 MySQL 驱动或者连接池性能要比 go 的差不少。
onanying
2020-07-27 15:35:43 +08:00
@mind3x 推论是对的,php 驱动是 pdo,是 c 写的,应该性能不会差,可能差距在 (基于 Swoole Channel 实现的连接池,pdo 支持协程是使用的 Hook 技术)和 (php 没有 jit,代码越多总执行时间差距越大) 这两方面
tinzing
2020-08-14 17:43:05 +08:00
其它 PHP 框架差距呢,譬如 TP,

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/693083

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX