性能测试:springboot-2.x vs actix-web-4.x benchmark

转载请注明出处 https://www.cnblogs.com/funnyzpc/p/15956465.html

前面

本次是对两款web框架做一次性能测试,这个测试做的很早,约在两个月前(也是actix-web4.0刚刚发布之后),目的是 比较有gc类web框架(springboot)与无gc类web框架(actix-web)的性能,分为带db查询不带db查询这两种情况,简单探究下web框架的性能瓶颈在哪儿,仅此而已。

顺带说下,apache JMeter实在太垃圾...,这里不细说了诶~ ️

准备测试

准备测试代码及数据

  • springboot2(java)

      @RestController
    public class Echo2Controller {
    @Autowired
    public DB1SQLDao db1SQLDao;
    // 带db资源的
    @GetMapping("/echo2")
    public Map<String,Object> echo(){
    /*
    <select id="findList2" resultType="java.util.Map">
    SELECT id,name,show_flag,create_date,code,parent_code from sys_menu limit 2
    </select>
    */
    List result = db1SQLDao.query("com.mee.xml1.tmp.findList2");
    Map<String, Object> res = ResultBuild.success("success");
    res.put("data",result);
    return res;
    } // 不带DB资源的
    @GetMapping("/echo3")
    public Map<String,Object> echo3(){
    /*
    public static final Map<String,Object> SUCCESS = new HashMap<String,Object>(2,1){{
    put("status",1);
    put("msg","成功");
    }};
    */
    return ResultBuild.SUCCESS;
    } }
  • actix-web4(rust)

        // 仅json资源请求
    pub async fn echo() -> HttpResponse{
    return HttpResponse::Ok().json(ResultBuild::<&str>::success());
    } // 带db的资源请求
    pub async fn sys_menu_list(/*req_body: String,*/db: web::Data<Pool>) -> HttpResponse{
    // async fn echo(/*req_body: String*/db: web::Data<Pool>) ->impl Responder {
    // let mut conn=db.get().await.unwrap();
    // let rows=conn.query("select * from sys_menu ",&[]).await.unwrap();
    // // get参数可以是str,也可以是i32,获取第几个。但是必须要指明获取的类型
    // let sys_menus = menu_list(&db).await.expect("---error---");
    let sys_menu_list = menu_list(&db).await;
    // HttpResponse::Ok().json(sys_menus)
    return HttpResponse::Ok().json(ResultBuild::success_with_data(sys_menu_list)); } async fn menu_list(pool: &Pool) -> Vec<SysMenu> {
    let client: Client = pool.get().await.expect("---error---");
    let stmt = client.prepare_cached("SELECT id,name,show_flag,create_date,code,parent_code from sys_menu limit 2").await.expect("--error2--");
    let rows = client.query(&stmt, &[]).await.expect("--error3");
    rows
    .into_iter()
    .map(|row| SysMenu {
    id: row.get(0),
    name: row.get(1),
    show_flag: row.get(2),
    create_date: row.get(3),
    code: row.get(4),
    parent_code: row.get(5),
    })
    .collect()
    }
  • 测试数据

    CREATE TABLE "sys_menu" (
    "id" numeric(24) primary key,
    "name" varchar(100) COLLATE "pg_catalog"."default" NOT NULL,
    "show_flag" int2 NOT NULL,
    "create_date" timestamp(6) NOT NULL,
    "create_by" varchar(64) COLLATE "pg_catalog"."default" NOT NULL,
    "code" varchar(8) COLLATE "pg_catalog"."default",
    "parent_code" varchar(8) COLLATE "pg_catalog"."default"
    );
    COMMENT ON TABLE "public"."sys_menu" IS '系统::菜单表'; INSERT INTO "public"."sys_menu"("id", "name", "show_flag", "create_date", "create_by", "code", "parent_code") VALUES ('20010616453200802', '主页', 1, '2020-11-27 03:09:21.714105', 'sys', '01', NULL);
    INSERT INTO "public"."sys_menu"("id", "name", "show_flag", "create_date", "create_by", "code", "parent_code") VALUES ('20010616513800803', '功能2', 1, '2020-11-27 03:09:24.25396', 'sys', '02', NULL);
    INSERT INTO "public"."sys_menu"("id", "name", "show_flag", "create_date", "create_by", "code", "parent_code") VALUES ('20010616525500804', '功能1', 1, '2020-12-09 11:44:04.478717', 'sys', '03', NULL);
    INSERT INTO "public"."sys_menu"("id", "name", "show_flag", "create_date", "create_by", "code", "parent_code") VALUES ('20010616545400805', '系统配置', 1, '2020-11-27 03:09:29.581216', 'sys', '04', NULL);
    INSERT INTO "public"."sys_menu"("id", "name", "show_flag", "create_date", "create_by", "code", "parent_code") VALUES ('20082918550500800', '系统配置', 1, '2020-11-27 03:09:40.177621', 'sys', '0401', '04');
    INSERT INTO "public"."sys_menu"("id", "name", "show_flag", "create_date", "create_by", "code", "parent_code") VALUES ('20082918561500801', '基础管理', 1, '2020-11-27 03:09:36.788131', 'sys', '0402', '04');
    INSERT INTO "public"."sys_menu"("id", "name", "show_flag", "create_date", "create_by", "code", "parent_code") VALUES ('20082918572200802', '用户配置', 1, '2020-11-27 03:09:42.242687', 'sys', '040101', '0401');
    INSERT INTO "public"."sys_menu"("id", "name", "show_flag", "create_date", "create_by", "code", "parent_code") VALUES ('20082918574400803', '菜单配置', 1, '2020-11-27 03:09:44.198666', 'sys', '040103', '0401');
    INSERT INTO "public"."sys_menu"("id", "name", "show_flag", "create_date", "create_by", "code", "parent_code") VALUES ('20082918574400813', '角色分配', 1, '2020-11-27 03:09:47.713889', 'sys', '040102', '0401');
    INSERT INTO "public"."sys_menu"("id", "name", "show_flag", "create_date", "create_by", "code", "parent_code") VALUES ('20082918581000804', '字典配置', 1, '2020-11-27 03:09:49.643454', 'sys', '040201', '0402');
    INSERT INTO "public"."sys_menu"("id", "name", "show_flag", "create_date", "create_by", "code", "parent_code") VALUES ('20082918584500805', '日志配置', 1, '2020-11-27 03:09:52.519771', 'sys', '040202', '0402');

1.1带DB资源的请求 (8c-8w)

目标资源通过数据库查询并序列化为json返回

  • 测试命令
    go-stress-testing-win -c 8 -n 80000 -u http://127.0.0.1:8011/mee_auto/echo2
    go-stress-testing-win -c 8 -n 80000 -u http://127.0.0.1:8080/echo

springboot (8c)

 ─────┬───────┬────────┬────────┬────────┬────────┬─────────┬─────────┬──────────┬─────────┬────────
耗时 │ 并发数 │ 成功数 │ 失败数 │ qps │ 最长耗时 │ 最短耗时 │ 平均耗时 │ 下载字节 │ 字节每秒 │ 错误码
─────┼───────┼───────┼────────┼─────────┼──────────┼──────────┼─────────┼─────────┼─────────┼────────
163s│ 8│ 79453│ 0│ 505.33 │ 454.05 │ 6.45 │ 15.83 │ │ │200:79453
164s│ 8│ 79911│ 0│ 505.41 │ 454.05 │ 6.45 │ 15.83 │ │ │200:79911
164s│ 8│ 80000│ 0│ 505.43 │ 454.05 │ 6.45 │ 15.83 │ │ │200:80000 ************************* 结果 stat ****************************
处理协程数量: 8
请求总数(并发数*请求数 -c * -n): 80000 总请求时间: 164.398 秒 successNum: 80000 failureNum: 0
************************* 结果 end ****************************

actix-web (8c)

─────┬───────┬───────┬───────┬────────┬────────┬────────┬─────────┬────────┬──────────┬────────
耗时 │ 并发数│ 成功数 │ 失败数│ qps │ 最长耗时│ 最短耗时 │ 平均耗时 │ 下载字节│ 字节每秒 │ 错误码
─────┼───────┼───────┼───────┼────────┼────────┼────────┼─────────┼────────┼─────────┼────────
135s│ 8│ 79025│ 0│ 610.44│ 112.56│ 5.30│ 13.11 │22,601,150│ 167,412│200:79025
136s│ 8│ 79617│ 0│ 610.49│ 112.56│ 5.30│ 13.10 │22,770,462│ 167,428│200:79617
137s│ 8│ 80000│ 0│ 610.67│ 112.56│ 5.30│ 13.10 │22,880,000│ 167,155│200:80000
************************* 结果 stat ****************************
处理协程数量: 8
请求总数(并发数*请求数 -c * -n): 80000 总请求时间: 136.878 秒 successNum: 80000 failureNum: 0
************************* 结果 end ****************************

1.2带DB资源的请求 (16c-8w)

目标资源通过数据库查询并序列化为json返回

  • 测试命令
    go-stress-testing-win -c 16 -n 80000 -u http://127.0.0.1:8011/mee_auto/echo2
    go-stress-testing-win -c 16 -n 80000 -u http://127.0.0.1:8080/echo

springboot (16c)

─────┬───────┬───────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────
耗时 │ 并发数 │ 成功数 │ 失败数 │ qps │ 最长耗时│ 最短耗时│ 平均耗时│ 下载字节│ 字节每秒│ 错误码
─────┼───────┼───────┼───────┼────────┼────────┼────────┼────────┼────────┼────────┼────────
146s│ 16│ 79294│ 0│ 558.06│ 553.22│ 8.20│ 28.67│ │ │200:79294
147s│ 16│ 79861│ 0│ 558.22│ 553.22│ 8.20│ 28.66│ │ │200:79861
147s│ 16│ 80000│ 0│ 558.07│ 553.22│ 8.20│ 28.67│ │ │200:80000
************************* 结果 stat ****************************
处理协程数量: 16
请求总数(并发数*请求数 -c * -n): 80000 总请求时间: 147.496 秒 successNum: 80000 failureNum: 0
************************* 结果 end ****************************

actix-web (16c)

─────┬───────┬───────┬───────┬────────┬─────────┬─────────┬────────┬──────────┬─────────┬────────
耗时│ 并发数 │ 成功数 │ 失败数│ qps │ 最长耗时 │最短耗时 │ 平均耗时 │ 下载字节 │ 字节每秒 │ 错误码
─────┼───────┼───────┼───────┼────────┼─────────┼─────────┼────────┼──────────┼─────────┼────────
139s│ 16│ 79468│ 0│ 584.20│ 259.02 │ 9.46 │ 27.39│22,727,848│ 163,508 │200:79468
140s│ 16│ 79991│ 0│ 584.31│ 259.02 │ 8.97 │ 27.38│22,877,426│ 163,408 │200:79991
140s│ 16│ 80000│ 0│ 584.33│ 259.02 │ 8.97 │ 27.38│22,880,000│ 163,248 │200:80000 ************************* 结果 stat ****************************
处理协程数量: 16
请求总数(并发数*请求数 -c * -n): 80000 总请求时间: 140.155 秒 successNum: 80000 failureNum: 0
************************* 结果 end ****************************

2.1不带DB资源的请求 (16c-16w)

目标资源仅仅为对象序列化为json返回

  • 测试命令
    go-stress-testing-win -c 16 -n 160000 -u http://127.0.0.1:8011/mee_auto/echo3
    go-stress-testing-win -c 16 -n 160000 -u http://127.0.0.1:8080/echo3

springboot (16c)

─────┬───────┬───────┬────────┬────────┬────────┬─────────┬────────┬─────────┬────────┬────────
耗时│ 并发数 │ 成功数 │ 失败数 │ qps │ 最长耗时│ 最短耗时│ 平均耗时│ 下载字节 │ 字节每秒 │ 错误码
─────┼───────┼───────┼────────┼────────┼────────┼────────┼─────────┼────────┼────────┼────────
74s│ 16│ 157047│ 0 │ 2705.19│ 283.33│ 0.50│ 5.91 │ │ │200:157047
75s│ 16│ 158698│ 0 │ 2696.52│ 283.33│ 0.50│ 5.93 │ │ │200:158698
76s│ 16│ 160000│ 0 │ 2693.35│ 283.33│ 0.50│ 5.94 │ │ │200:160000
************************* 结果 stat ****************************
处理协程数量: 16
请求总数(并发数*请求数 -c * -n): 160000 总请求时间: 75.811 秒 successNum: 160000 failureNum: 0
************************* 结果 end ****************************

actix-web (16c)

─────┬───────┬───────┬───────┬────────┬────────┬─────────┬────────┬──────────┬────────┬────────
耗时│ 并发数 │ 成功数 │ 失败数│ qps │ 最长耗时│ 最短耗时 │ 平均耗时│ 下载字节 │ 字节每秒│ 错误码
─────┼───────┼───────┼───────┼────────┼────────┼─────────┼────────┼──────────┼────────┼────────
43s│ 16│ 155741│ 0│ 4620.61│ 113.40│ 0.64 │ 3.46│9,811,683 │ 228,177│200:155741
44s│ 16│ 158948│ 0│ 4608.00│ 113.40│ 0.64 │ 3.47│10,013,724│ 227,583│200:158948
44s│ 16│ 160000│ 0│ 4609.79│ 113.40│ 0.89 │ 3.47│10,080,000│ 227,478│200:160000
************************* 结果 stat ****************************
处理协程数量: 16
请求总数(并发数*请求数 -c * -n): 160000 总请求时间: 44.312 秒 successNum: 160000 failureNum: 0
************************* 结果 end ****************************

2.2不带DB资源的请求 (8c-8w)

目标资源仅仅为对象序列化为json返回

  • 测试命令
    go-stress-testing-win -c 8 -n 80000 -u http://127.0.0.1:8011/mee_auto/echo3
    go-stress-testing-win -c 8 -n 80000 -u http://127.0.0.1:8080/echo3

springboot (8c)

─────┬───────┬───────┬───────┬────────┬────────┬────────┬─────────┬────────┬────────┬────────
耗时 │ 并发数 │ 成功数 │失败数 │ qps │最长耗时│最短耗时 │平均耗时 │下载字节│字节每秒 │ 错误码
─────┼───────┼───────┼───────┼────────┼────────┼────────┼─────────┼────────┼────────┼────────
52s│ 8│ 76730│ 0│ 1820.31│ 253.83│ 0.30│ 4.39 │ │ │200:76730
53s│ 8│ 78467│ 0│ 1826.48│ 253.83│ 0.30│ 4.38 │ │ │200:78467
54s│ 8│ 80000│ 0│ 1834.15│ 253.83│ 0.30│ 4.36 │ │ │200:80000
************************* 结果 stat ****************************
处理协程数量: 8
请求总数(并发数*请求数 -c * -n): 80000 总请求时间: 53.885 秒 successNum: 80000 failureNum: 0
************************* 结果 end ****************************

actix-web (8c)

──────┬───────┬───────┬────────┬───────┬─────────┬─────────┬─────────┬─────────┬────────┬────────
耗时 │并发数 │ 成功数 │ 失败数 │ qps │ 最长耗时│ 最短耗时│ 平均耗时│ 下载字节 │ 字节每秒 │ 错误码
─────┼───────┼───────┼────────┼────────┼─────────┼────────┼─────────┼──────────┼────────┼────────
12s│ 8│ 69187│ 0 │ 7257.03│ 5.98 │ 1.00│ 1.10 │4,358,781 │ 363,207│200:69187
13s│ 8│ 74735│ 0 │ 7232.76│ 5.98 │ 0.99│ 1.11 │4,708,305 │ 362,149│200:74735
14s│ 8│ 80000│ 0 │ 7229.78│ 5.98 │ 0.00│ 1.11 │5,040,000 │ 361,557│200:80000 ************************* 结果 stat ****************************
处理协程数量: 8
请求总数(并发数*请求数 -c * -n): 80000 总请求时间: 13.940 秒 successNum: 80000 failureNum: 0
************************* 结果 end ****************************

请求一览【带DB数据请求】

并发数 并发请求数 框架 qps 平均耗时
8 80000 springboot 505 15.83
8 80000 actix-web 610 13.10
16 80000 springboot 558 28.66
16 80000 actix-web 584 27.38

请求一览【不带DB数据请求(纯代码json)】

并发数 并发请求数 框架 qps 平均耗时
8 80000 springboot 1826 4.38
8 80000 actix-web 7232 1.11
16 160000 springboot 2696 5.93
16 160000 actix-web 4609 3.47

简单总结

首先一个重要的前提是我的电脑是 i5 8核32GB 的配置

  • 1.在带DB数据请求的下,不管是8个并发还是16个并发 springbootactix-web两者的qps相距并不大,在cpu超载(16c)下平均耗时更多,据此可以得出 并发数与所在的机器配置是成正比的:硬件配置在其合理的并发下性能以及延迟是最优的

  • 2.在不带DB的数据请求下,也显示了1的结论,同时也能看到随着cpu超载 延迟以及qps也会逐渐变得糟糕

  • 3.对于springboot、actix-web这两款框架,无gc类语言在合适的并发&硬件配置下 性能(延迟qps内存cpu利用率)相对与 gc类框架是存在优势的

  • 4.对于web类框架(不管是gc类的还是非gc类的框架)他们的性能除了并发&硬件配置外 也取决于整个请求链路中性能最低的那一环:通过以上可以大致分析出性能一般是出在DB数据查询这一块儿,所以良好的DB架构及缓存配置可以有效提高应用的性能及硬件的利用率

    以上仅为个人测试所得结果,如有谬误恳请指正~

简单性能测试:springboot-2.x vs actix-web-4.x benchmark的更多相关文章

  1. 一个简单的SpringBoot入门程序

    1. 使用IDEA构建Maven项目 <?xml version="1.0" encoding="UTF-8"?> <project xmln ...

  2. springboot入门系列(一):简单搭建springboot项目

    Spring Boot 简单介绍 Spring Boot 本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速.敏捷地开发新一代基于Spring框架的应用程序.也就是说,它并不是用来替代S ...

  3. Greenplum 简单性能测试与分析

    如今,多样的交易模式以及大众消费观念的改变使得数据库应用领域不断扩大,现代的大型分布式应用系统的数据膨胀也对数据库的海量数据处理能力和并行处理能力提出了更高的要求,如何在数据呈现海量扩张的同时提高处理 ...

  4. Springboot搭建SSM+JSP的web项目

    Springboot搭建SSM+JSP的web项目 一:创建项目结构: 项目结构分为三个部分: 1 后端项目开发文件: 包: Util         工具包 Mapper      db层 Serv ...

  5. Mininet实验 设置带宽之简单性能测试

    原文:设置带宽之简单性能测试 这个实验主要还是说明通过python程序来设定Mininet中的链路带宽. 目的: Python脚本实现自定义拓扑 设置链路的带宽.延迟及丢包率 iperf测试主机间的带 ...

  6. .Net core2.0日志组件Log4net、Nlog简单性能测试

    .Net core之Log4net.Nlog简单性能测试 比较log4net.nlog的文件写入性能(.netcore环境),涉及代码和配置如有不正确的地方,还请批评指正. 原创,转载请著名出处:ht ...

  7. 一个最简单的springboot

    现在项目里使用springboot,平时开发并不太关注springboot的一些基本配置,现在想整理一下springboot相关内容. 实际开发中都会因为各种业务需求在springboot上添加很多东 ...

  8. snaic和tornado的简单性能测试

    操作系统 : CentOS7.3.1611_x64 Python 版本 : 3.6.8 tornado版本:6.0.2 snaic版本:19.9.0 CPU : Intel(R) Core(TM) i ...

  9. 简单实现SpringBoot启动

    一.准备: IDEA 使用简单手写导包实现spring boot,未使用idea自带的spring创建方法 可以更加简单理解springboot启动过程 二.开始 1.打开idea创建project ...

随机推荐

  1. js 改变页面元素的内容

    改变页面标签里的内容 (方法) innerText innerHTML (常用)   代码示例 <div></div> <p> 我是文字 <span>1 ...

  2. WMS、WFS、WCS、WPS、WMTS、WMSC、TMS等常见地图服务的区别

    WebGIS的开发者经常需要面对各种地图服务规范,例如WMS.WFS.WCS.WPS.WMTS.TMS.WMSC等.因此了解这些服务的内容是相当重要的,这里对常见的服务进行了整理. OGC联盟: 开放 ...

  3. MKL库奇异值分解(LAPACKE_dgesvd)

    对任意一个\(m\times n\)的实矩阵,总可以按照SVD算法对其进行分解.即: \[A = U\Sigma V^T \] 其中\(U.V\)分别为\(m\times m.n\times n\)的 ...

  4. zookeeper的linux安装

    wget下载(很慢):wget http://archive.apache.org/dist/zookeeper/zookeeper-3.4.11/zookeeper-3.4.11.tar.gz 或者 ...

  5. Linux 系统安装 AutoFs 挂载服务

    关注「开源Linux」,选择"设为星标" 回复「学习」,有我为您特别筛选的学习资料~ 作者: Escape 链接: https://escapelife.github.io/pos ...

  6. CentOS 8及以上版本配置IP的方法,你 get 了吗

    接上篇文章讲了 Ubuntu 18及以上版本的配置方法,本文再来讲讲 CentOS 8 及以上版本配置 IP 的方法. Centos/Redhat(8.x) 配置 IP 方法 说明:CentOS 8 ...

  7. .NET性能优化-为结构体数组使用StructLinq

    前言 本系列的主要目的是告诉大家在遇到性能问题时,有哪些方案可以去优化:并不是要求大家一开始就使用这些方案来提升性能. 在之前几篇文章中,有很多网友就有一些非此即彼的观念,在实际中,处处都是开发效率和 ...

  8. 【多线程】线程同步 synchronized

    由于同一进程的多个线程共享同一块存储空间 , 在带来方便的同时,也带来了访问 冲突问题 , 为了保证数据在方法中被访问时的正确性 , 在访问时加入 锁机制synchronized , 当一个线程获得对 ...

  9. 每天一个 HTTP 状态码 203

    203 Non-Authoritative Information 203 Non-Authoritative Information 'Non-Authoritative Informative' ...

  10. Docker安装Mycat和Mysql进行水平分库分表实战【图文教学】

    一.前言 小编最近公司有个新的需求,数据量比较大,要涉及到分库分表.大概了解了一些主流的中间件,使用和网上资料比较多的是Mycat和sharding-jdbc,小编比较倾向于Mycat.原因很简单就是 ...