Проблема производительности Rust - код высокой сложности - PullRequest
0 голосов
/ 31 марта 2020

Я купил RUST по его производительности, поэтому я решил перевести один проект, где производительность имеет большое значение, с JAVA 11 до Rust.

Дело в том, что версия, написанная в JAVA производительности намного лучше более 3x в одном потоке, + 10X в многопоточности

Для целей контекста: Самый сложный код - это функция, которая пытается найти задание между двумя наборами представьте себе, что у вас есть дома и магазины, магазины имеют фиксированную вместимость, а в домах есть необходимость, вы хотите найти лучшее назначение, чтобы ходить меньше.

Учитывая все это, я думаю, что проблема в том, как Я использую переменные, может быть, clone () вызывается слишком часто автоматически, может быть, обращение к ссылкам вызывает какое-то неизвестное поведение.

Любое обновление, которое сокращается, пока l oop время, будет большим, потому что оно повторяется более 5000 раз. Извините за длинный код, но я думаю, что все имеет значение в этом случае. Вы не можете скопировать и вставить этот код, если хотите, я могу отправить вам ссылку на проект git.

PD: Я работаю с car go run - выпуск

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)
}

1 Ответ

0 голосов
/ 03 апреля 2020

Теперь у меня есть увеличение в 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% поиска нового значения

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...