• 简单性能测试:springboot2.x vs actixweb4.x benchmark


    性能测试: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架构及缓存配置可以有效提高应用的性能及硬件的利用率

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

  • 相关阅读:
    How to join (ap invoice distributions all) AP table info with PO Table
    Order Management APIs Oe_Order_Pub
    R12 Oe_Order_Pub API
    物料搬运单
    Process Order API In Order Management(详细)
    ap_invoice_distributions_all与PO表关联问题
    分配用人单位
    oe_order_pub 更改订单行数量,提示此更改的原因未提供或无效
    Order Management APIs
    提前期
  • 原文地址:https://www.cnblogs.com/funnyzpc/p/15956465.html
Copyright © 2020-2023  润新知