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 上试用。请注意,您需要一个夜间编译器,因为它使用了一个不稳定的功能。
我已经将我在 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 上试用。请注意,您需要一个夜间编译器,因为它使用了一个不稳定的功能。