Rust - 为什么我的程序执行速度非常慢 - 比使用 Node 在 JavaScript 中编写的相同程序慢 5 倍以上

Rust - why is my program performing very slowly - over 5 times slower than the same program written in JavaScript using Node

我已经将我在 JavaScript 中制作的应用程序转换为 Rust 以提高性能。我正在学习编程,所有应用程序所做的就是计算一个范围内任何数字的乘法持久性。它将所有数字相乘形成一个新数字,然后重复直到数字小于 10。

我的问题是,我用 JavaScript 编写的程序比用 Rust 编写的程序快 5 倍以上。我一定是在某处将字符串转换为整数时做错了什么,我什至尝试将 i128 交换为 i64,但没什么区别。

如果我运行 "cargo 运行 --release" 还是比较慢!

请有人看一下我的代码,看看是否有任何部分导致了问题?提前谢谢你:)

fn multiplicative_persistence(mut user_input: i128) -> i128 {
    let mut steps: i128 = 0;
    let mut numbers: Vec<i128> = Vec::new();
    while user_input > 10 {
        let string_number: String = user_input.to_string();
        let digits: Vec<&str> = string_number.split("").collect();
        let mut sum: i128 = 1;
        let digits_count = digits.len();

        for number in 1..digits_count - 1 {
            sum *= digits[number].parse::<i128>().unwrap();
        }

        numbers.push(sum);

        steps += 1;
        user_input = sum;
    }

    return steps;
}
fn main() {
    // let _user_input: i128 = 277777788888899;

    let mut highest_steps_count: i128 = 0;
    let mut highest_steps_number: i128 = 0;

    let start: i128 = 77551000000;
    let finish: i128 = 1000000000000000;

    for number in start..=finish {
        // println!("{}: {}", number, multiplicative_persistence(number));
        if multiplicative_persistence(number) > highest_steps_count {
            highest_steps_count = multiplicative_persistence(number);
            highest_steps_number = number;
        }
        if number % 1000000 == 0 {
            println!("Upto {} so far: {}", number, highest_steps_number);
        }
    }

    println!("Highest step count: {} at {}", highest_steps_number, highest_steps_count);
}

我打算在函数中使用数字变量,但我还没有学到足够的知识来知道如何正确地return它作为一个关联数组。

也许问题在于将数字转换为字符串,然后 re-converting 再次将其转换为数字并不是那么快,而且是可以避免的。您不需要这个中间步骤:

fn step(mut x: i128) -> i128 {
  let mut result = 1;
  while x > 0 {
    result *= x % 10;
    x /= 10;
  }
  result
}

fn multiplicative_persistence(mut user_input: i128) -> i128 {
  let mut steps = 0;
  while user_input > 10 {
    user_input = step(user_input);
    steps += 1;
  }
  steps
}

编辑 出于好奇,我想知道瓶颈是否真的是由于字符串转换造成的,还是由于代码的其余部分有些浪费。这是一个不调用 .split("")、不 re-allocate 中间向量的示例,并且只分配一次,而不是在每个步骤中分配字符串。

#![feature(fmt_internals)]

use std::fmt::{Formatter, Display};

fn multiplicative_persistence(user_input: i128) -> i128 {
    let mut steps = 0;
    let mut digits = user_input.to_string();
    while user_input > 10 {
        let product = digits
            .chars()
            .map(|x| x.to_digit(10).unwrap())
            .fold(1, |acc, i| acc*i);
        digits.clear();
        let mut formatter = Formatter::new(&mut digits);
        Display::fmt(&product, &mut formatter).unwrap();
        steps += 1;
    }
    steps
}

我基本上内联了 .to_string() 执行的字符串转换,以便 re-use already-allocated 缓冲区,而不是每次迭代 re-allocating。您可以在 playground 上试用。请注意,您需要一个夜间编译器,因为它使用了一个不稳定的功能。