You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust循环POC运行极慢原因排查:对比Go性能疑问

嘿,作为Rust新手能写出POC已经很棒了!咱们来一步步拆解你的代码里拖慢性能的问题,让它发挥出Rust应有的速度:

核心性能问题分析

你的代码慢的主要原因集中在这几点:

1. 夸张到离谱的循环次数

最外层的for _i in 0..1000000000是10亿次循环!哪怕每次循环只做极简单的操作,10亿次也会消耗巨量时间——这绝对是最大的性能杀手。你是不是笔误把测试次数写错了?比如本来想写1000次而非10亿次?Go版本能几秒完成,大概率是没有这么夸张的循环次数。

2. 动态Value的频繁无类型访问开销

serde_json::Value是动态类型的JSON表示,每次访问data["tl"][i]["t"]这类路径时,都会做:

  • 哈希表查找(因为Value的对象是哈希表结构)
  • 运行时类型断言(比如as_array().unwrap())
    这些操作在循环里重复执行,累积起来的开销非常大。而Go如果用结构体解析JSON,是静态类型访问,没有这些运行时开销。

3. 不必要的重复计算

你每次内层循环都重复调用data["tl"].as_array().unwrap().len()、data["el"].as_array().unwrap().len()——这些值在整个rule函数执行过程中是完全不变的,却被重复计算了无数次。

4. 字符串比较的额外开销

data["tl"][i]["t"] == "my_value"这类比较,需要先把Value转换成字符串再做对比;如果用静态结构体,直接是字符串切片的比较,效率高得多。


优化后的代码示例

我们用静态类型结构体代替动态Value,提前提取不变值,修正循环次数,再加上一些Rust风格的优化:

首先确保Cargo.toml里的依赖正确:

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

优化后的代码:

use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs::File;
use std::io::BufReader;

// 定义与JSON结构匹配的静态类型结构体
#[derive(Debug, Deserialize, Serialize)]
#[serde(borrow)] // 直接借用JSON中的字符串,避免不必要的克隆
struct TlEntry<'a> {
    t: &'a str,
    refu: &'a str,
    eu: &'a str,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(borrow)]
struct ElEntry<'a> {
    is_inpatient: bool,
    eu: &'a str,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(borrow)]
struct Data<'a> {
    tl: Vec<TlEntry<'a>>,
    el: Vec<ElEntry<'a>>,
}

fn rule(data: &Data) {
    let ru = "589ea4b8-99d1-8d05-9358-4c172c10685b";
    
    // 提前构建el的索引:用eu作为key,快速匹配
    let mut el_index = HashMap::new();
    for el_entry in &data.el {
        if el_entry.is_inpatient {
            el_index.entry(el_entry.eu).or_insert_with(Vec::new).push(el_entry);
        }
    }

    // 假设这里是笔误,改成1000次测试循环(你可以根据需求调整)
    for _i in 0..1000 {
        for tl_entry in &data.tl {
            if tl_entry.t == "my_value" && tl_entry.refu == ru {
                // 直接通过索引查找,无需遍历整个el数组
                if let Some(matching_entries) = el_index.get(tl_entry.eu) {
                    for _entry in matching_entries {
                        // 这里放你的业务逻辑
                    }
                }
            }
        }
    }
}

fn start() -> Result<(), Box<dyn std::error::Error>> {
    let file = File::open("../../data.json")?;
    let reader = BufReader::new(file);
    // 解析为静态类型Data,而非动态Value
    let data: Data = serde_json::from_reader(reader)?;
    rule(&data);
    Ok(())
}

fn main() {
    if let Err(e) = start() {
        eprintln!("运行出错: {}", e);
        std::process::exit(1);
    }
}

额外优化点说明

  1. #[serde(borrow)]的作用:让结构体直接借用JSON中的字符串,避免解析时复制字符串,节省内存和时间。
  2. 哈希表索引:把el数组转换成以eu为key的哈希表,让内层查找从O(N)变成O(1),如果el数组很大,性能提升会非常显著。
  3. 迭代器代替索引循环:Rust的迭代器比手动索引更高效,也更符合语言习惯。

调整后,这段代码的性能应该能轻松超过Go版本——毕竟Rust的静态类型和零开销抽象不是吹的!

内容的提问来源于stack exchange,提问作者Fmstrat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 15:32:34