【问题标题】:Rust performance issue - High complexity codeRust 性能问题 - 高复杂度代码
【发布时间】:2020-03-31 00:47:21
【问题描述】:

我购买 RUST 是因为它的性能,所以我决定将一个性能非常重要的项目从 JAVA 11 翻译成 Rust。

问题是用 JAVA 编写的版本在单线程中性能比 3 倍以上,在多线程中 +10 倍以上

出于上下文目的: 最复杂的代码是一个函数,它试图在 2 个集合之间找到一个分配,假设您有房屋和商店,商店有固定容量和房子有必需品,你想找到最好的分配少走。

考虑到这一切,我想问题在于我如何使用变量,可能 clone() 被自动调用太多,可能引用访问导致一些未知行为。

任何减少 while 循环时间的升级都会很棒,因为它会迭代超过 5000 次。很抱歉代码很长,但我认为在这种情况下一切都是相关的。如果需要,您不能复制和粘贴此代码,我可以将 git 项目链接发送给您。

PD:我正在使用 cargo run --release

pub fn evaluate(elem: &Element) -> EvaluatedElement {

    let p1 = properties::get_cast::<f64>("p1");
    let p2 = properties::get_cast::<usize>("p2");
    let p3 = properties::get_cast::<usize>("p3");
    let p4 = properties::get_cast::<f64>("p4");
    let p5 = properties::get_array::<usize>("p5");

    let mut kinds1 = kind1::get_map(); //almost 300 elements
    let kinds2 = = kind2::get_map(); //almost 300 elements

    let usables = elem.usables();

    for (i, &a) in usables.iter().enumerate() {
        if !a {
            &kinds1.remove(&(i + 1));
        }
    }

    let mut assignations = HashMap::new();

    for k in (1..=p2).rev() {
        let mut kinds2_sub = HashMap::with_capacity((&kinds2).len());
        for (_, p) in kinds2.iter() {
            if p.val1[k - 1] == 0 {
                continue;
            }

            &kinds2_sub.insert(p.id, Kind2Sub {
                parent: p.clone(),
                val2: p.val1[k - 1],
                val3: std::f64::MAX,
                kind1_id: std::usize::MAX,
            });
        }

        let mut opt_kind1_id: Option<usize> = Option::None;

        while !&kinds2_sub.is_empty() {//arround 5500 times loop

            for mut l in kinds2_sub.values_mut() {
                match opt_kind1_id {
                    None => (),
                    Some(id) => if !l.kind1_id == id { continue; },
                }

                l.val3 = std::f64::MAX;
                l.kind1_id = std::usize::MAX;

                for b in kinds1.values_mut() {
                    let dist_b_l = calc_dist(b.id, l.id);
                    if dist_b_l > p4
                        || (p1 as usize).min(l.val2) > p4 + b.val3
                        || b.val2 < k
                        || (l.val2 < (2 * p4) && (b.val3 as i16 - l.val2 as i16) < 0)
                    { continue; }

                    let tmp = dist_b_l * p1.min(l.val2 as f64);

                    if l.val3 > tmp {
                        l.val3 = tmp;
                        l.kind1_id = b.id;
                    }
                }
            }

            let lc = kinds2_sub.values_mut().min_by(|x, y| x.val3.partial_cmp(&y.val3).unwrap()).unwrap();
            let obc = kinds1.get_mut(&lc.kind1_id);
            let bc = obc.unwrap_or_else(|| {
                panic!("No assignation able")
            });
            let b_c_id = (*bc).id;
            let l_c_id = (*lc).id;

            let time = if lc.val2 < (2usize * p1 as usize) { lc.val2 } else { p1 as usize };
            let val = (*bc).val3 as i16 - time as i16;

            let assignation = Assignation { kind1_id: (*bc).id, kind2_id: lc.id, val3: k, val4: 0 };
            let assignation_id = assignation.id();//id() = fn concatenate first 3 values
            if !assignations.contains_key(&assignation_id) {
                assignations.insert(assignation.id(), assignation);
            }
            let mut assignation = assignations.get_mut(&assignation_id).unwrap_or_else(|| panic!("Assignation not found {}", assignation_id));

            if val >= 0 {
                assignation.val4 += time;
                lc.val2 -= time;
                (*bc).val3 -= time;
            } else {
                assignation.val4 += (*bc).val3;
                lc.val2 -= (*bc).val3;
                (*bc).val3 = 0;
            }

            if (*bc).val3 < p4 {
                &kinds1.remove(&b_c_id);
            }

            if lc.val2 == 0 {
                &kinds2_sub.remove(&l_c_id);
            }

            opt_kind1_id = Some(b_c_id);
        }
    }


    let assignations_values = assignations.iter().map(|(_, v)| v.clone()).collect();

    EvaluatedElement::evaluation(assignations_values)
}

【问题讨论】:

标签: performance variables rust


【解决方案1】:

现在我有 4 倍的增长。

        Step  Value   Time  Used Stores
RUST -> BI 90 2672540 28057 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0]
Java -> BI 90 2672625  4704 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0]
FIX: -> BI 90 2672540  1093 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0]
  • “错误”

    match opt_kind1_id {
        None => (),
        Some(id) => if !l.kind1_id == id { continue; },
    }
    
  • 修复

    if let Some(id) = opt_kind1_id {
        if l.kind1_id != id {
            continue;
        }
    }
    

这个继续跳过了 90% 的寻找新值

【讨论】:

    猜你喜欢
    • 2021-03-24
    • 1970-01-01
    • 2023-01-12
    • 1970-01-01
    • 2011-09-07
    • 1970-01-01
    • 2018-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多