V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
onanying
V2EX  ›  PHP

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

  •  4
     
  •   onanying · 2020-07-25 19:41:27 +08:00 · 2613 次点击
    这是一个创建于 706 天前的主题,其中的信息可能已经有所发展或是发生改变。

    昨天在 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
    
    • 进程
    [[email protected]~]$ 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
    
    • 响应内容
    [[email protected]~]$ curl http://127.0.0.1:9501/
    [{"id":1,"name":"3"}]
    
    • 测试结果:测试了很多次,在 9936.36 ~ 10080.25 左右
    [[email protected]~]$ 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 &
    
    • 进程
    [[email protected]~]$ ps -ef| grep bee
    nobody   27316     1  0 18:37 ?        00:00:00 ./gobeego_linux
    
    • 响应内容
    [[email protected]~]$ curl http://127.0.0.1:8989/index
    [{"id":1,"name":"3"}]
    
    • 测试结果:测试了很多次,在 16306.15 ~ 16327.19 左右
    [[email protected]~]$ 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 |

    第 1 条附言  ·  2020-07-25 21:00:57 +08:00

    测试结果 mix 比 beego 数据库查询+序列化的综合性能要低 38.3%,上面我写错了!

    第 2 条附言  ·  2020-07-27 11:39:25 +08:00
    • 开启 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 |

    第 3 条附言  ·  2020-07-27 11:48:48 +08:00

    V2EX 没办法修改内容,完整的测试报告在这里:

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

    我怀疑数据库连接池的行为或者数据库驱动有什么不同,建议拿掉 json 序列化再测一下。
    ben1024
        10
    ben1024  
       2020-07-27 09:10:33 +08:00
    可以尝试下
    控制下变量,单次只测试一点
    还有应用预热
    ben1024
        11
    ben1024  
       2020-07-27 09:11:39 +08:00
    SQL 查询还需要加个随机数,避免 SQL 缓存
    onanying
        12
    onanying  
    OP
       2020-07-27 11:40:27 +08:00
    @wei193 更换模式后 beego 性能得到了显著提升,测试结果 mix 比 beego 数据库查询+序列化的综合性能要低 48.2%
    onanying
        13
    onanying  
    OP
       2020-07-27 11:41:44 +08:00
    @mind3x 移除序列化后测试结果变化非常小,说明序列化在这个测试中影响很小,也就是序列化相对于 db 查询来说,对整体性能影响比我们想象的要小很多。我在帖子后面追加了相关测试,https://zhuanlan.zhihu.com/p/163700975 也有完整的测试细节
    onanying
        14
    onanying  
    OP
       2020-07-27 11:43:40 +08:00
    @ben1024 正式使用环境也是有 sql 缓存的,这个感觉就没必要的,主要是看框架+语言直接,大概模拟一点真实业务场景,看看差异
    mind3x
        15
    mind3x  
       2020-07-27 15:24:41 +08:00
    @onanying 所以综合你之前无数据库的 benchmark 结果,总的推论是 php 的 MySQL 驱动或者连接池性能要比 go 的差不少。
    onanying
        16
    onanying  
    OP
       2020-07-27 15:35:43 +08:00
    @mind3x 推论是对的,php 驱动是 pdo,是 c 写的,应该性能不会差,可能差距在 (基于 Swoole Channel 实现的连接池,pdo 支持协程是使用的 Hook 技术)和 (php 没有 jit,代码越多总执行时间差距越大) 这两方面
    tinzing
        17
    tinzing  
       2020-08-14 17:43:05 +08:00
    其它 PHP 框架差距呢,譬如 TP,
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2456 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 02:39 · PVG 10:39 · LAX 19:39 · JFK 22:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.