太快了! Rust 太快了!

4 天前
 serverKnignt

1. 背景

LZ 是一名在职的 Java boy ,花了上周一周的时间入门了 Rust 。周末使用 axum 写了个 web 项目,模拟了 SpringMVC 的架构。

2. 对比

均在我 mac 笔记本中进行测试

2.1 占用资源

这里可能不太公平。
Java 项目用了我之前的开源项目,虽然是个完整的项目但是也不是很大。没有打包成 jar ,使用 idea 启动,通过活动检测器根据 pid 查找发现占用内存494.2MB,JVM 配置:-Xms256m -Xmx4g 。
Rust 启动后发现内存占用为 2.0MB!!! 我人都傻了,虽然说是个很简单的项目,但是项目中必要的功能都有。

2.2 压测

为了进一步的看到差距,我开始了压测,代码如下。为了减少变量,没有加入 IO 操作,但也是正常的业务功能。
JAVA

      @Override
    public AiUserVO loginTest(AiUserReq userReq) {
        CommonUtils.checkArgs(userReq.getAccountNo(),userReq.getPassword());
        AiUser user = AiUser.builder().accountNo("admin").password("admin").name("admin").build();
        user.setId(1941040891798581249L);
        //校验登录
//        checkLogin(user,userReq);
        AiUserVO result = ConvertUtils.beanProcess(user, AiUserVO.class);
        //处理用户角色
//        processUserRole(user,result);
        //生成 token
        String token = genToken(user);
        result.setToken(token);
        //放入 redis
        String key = CacheKeyEnum.format(CacheKeyEnum.ADMIN_LOGIN_KEY,user.getId(),token);
        SysCacheUserDto sysCacheUserDto = ConvertUtils.beanProcess(result, SysCacheUserDto.class);
        //删除原始 token
//        removeToken(user.getId());
//        redisCacheComponent.set(key,JSONObject.toJSONString(sysCacheUserDto),TimeConstant.ONE_DAY * 12);
        return result;
    }

RUST

pub async fn login(user:UserReq)->Res<UserVO> {
    // 查询逻辑
    let user_do = match query_user(&user.account_no, &user.password).await {
        Some(user_do) => user_do,
        None => return Res::build(FAIL),
    };
    let mut user_vo:UserVO = user_do.into();
    //加密
    let token = match security_utils::aes_encrypt(&user_vo.id.to_string()) {
        Ok(token) => token,
        Err(_) => return Res::build(FAIL),
    };
    user_vo.token = token;
    let key = SYSTEM_USER.key().format(&[&user_vo.id.to_string()]);
    //删除缓存
    GlobalCache::del(&key);
    //放入缓存
    GlobalCache::set(key,serde_json::to_string(&user_vo).unwrap());
    Res::success(user_vo)
}

/**
 * 查询用户
 */
async fn query_user(account_no:&str,pwd:&str)->Option<UserDO> {
    let user = UserDO{
        id:1912753992656158721,
        name:"admin".to_string(),
        account_no:"admin".to_string(),
        status:true,
    };
    Some(user)
}

压测配置如下

Name: 线程组-30
Number of Threads: 200
Ramp-Up Period: 30 
Loop Count: 1
Scheduler:
  Duration: 90

Name: 线程组-90
Number of Threads: 200
Ramp-Up Period: 30   
Loop Count: 1
Scheduler:
  Startup Delay: 90
  Duration: 90

压测流程如下

阶段一:0~30 秒启动 200 线程 → 持续到第 90 秒
阶段二:从第 90 秒开始,30 秒内启动 300 线程 → 持续到第 180 秒

压测结果对比如下

指标 RUST JAVA 差异
平均响应时间 3~4 ms 6~8 ms ↑ 上升 50%~100%
最大响应时间 17 ms 26 ms ↑ 上升 53%
99% 百分位 11~15 ms 15~20 ms ↑ 上升 30%~45%
吞吐量 6.7 → 10.0 req/sec 6.7 → 10.0 req/sec ✅ 相同
异常率 0% 0% ✅ 相同
数据包大小 294 B 489 B ↑ 增加 66%

2944 次点击
所在节点    Rust
26 条回复
Georgedoe
4 天前
写业务代码快才是真的快,程序跑的快不快和我有啥关系(狗头)
zpvip
4 天前
还是太年轻了, 快有什么用, 小网站不差几毫秒, 大网站堆机器, 便宜得很. 用 Rust 写 Web, 这是没有困难创造困难.

Web 界我只推 Ruby on Rails, 虽然 js, php, Java, C# 更流行, 但这是老板思维, 招人容易, 开人没负担, 工资给得低, 还随便 PUA. 从程序员的角度, 还是 Ruby on Rails 好用.

如果程序员不改变想法, 都替老板着想, 只能让好的东西埋没, 整天被限制在所谓工程化的泥沼中当螺丝钉.
VeryZero
3 天前
让我想起来某次代码评审,有人让我少用 System.currentTimeMillis(),能省一点是一点,积少成多,宁愿不要时间统计的功能🐶
montaro2017
3 天前
程序跑得快有什么用,代码写的又不快 ,至于服务器 CPU 和内存,和我有什么关系
nebkad
3 天前
@zpvip 非常赞同你所说的 “如果程序员不改变想法, 都替老板着想, 只能让好的东西埋没 ”

我一直都觉得 Java 甚至 golang 这种编程语言,都是为了过度分工的大规模开发而设计的编程语言。
特点是语法不花哨,但是语言表现力也差,不适合自由程序员协作,倒是适合码农协作。
所以像 Rust 这种,对性能敏感,表现力也还可以的语言,才是自由程序员们依靠自身技艺水平,击败累赘堆砌代码的项目的杀手锏。

以上观点,请你批评。
zengxs
2 天前
Rust 做业务太费劲了,只适合做那种代码逻辑长期稳定的项目

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

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

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

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

© 2021 V2EX