【发布时间】: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)
}
【问题讨论】:
-
我认为这样的讨论太笼统了,可能更适合users.rust-lang.org
-
我认为一些专家的眼睛会意识到一些像我犯的错误,我花了 30 多个小时才找到它。
标签: performance variables rust