Note: the code below comes from a solution to one of the basic introductory programming tasks (i.e. people learning about loops and stuff). Of course, the algorithm itself can be improved a lot, but the point here is about the raw performance of compilers, and not about the algorithm or code style. The task was to find a number within the range with the biggest sum of its divisors. I just got curious as to how different compilers will handle the “same” code, and this is where I noticed that in Rakudo something is a bit weird.
For the code below, changing for $a..$b -> $i {
to for $a..$b -> int $i {
gives a 10x time boost for the entire program. Doing the same but with uint
does not work as fast.
Just as a reference, without native ints the program runs significantly slower than the python version, but after changing the loop variable it runs significantly faster than the python version.
Raku (without int )
| 168.622s
|
Raku (with int )
| 12.261s
|
Python | 43.420s
|
Rust | 1.816s
|
Code (slow):
#!/usr/bin/env raku
my $a = +prompt;
my $b = +prompt;
my $max = 0;
my $x = 0;
for $a..$b -> $i {
my $sum = 0;
for 1..$i -> $j {
if $i %% $j {
$sum += $j;
}
}
if $sum >= $max {
$max = $sum;
$x = $i;
}
}
say “$x $max”;
Code (fast):
#!/usr/bin/env raku
my $a = +prompt;
my $b = +prompt;
my $max = 0;
my $x = 0;
for $a..$b -> int $i { #← this line was changed
my $sum = 0;
for 1..$i -> int $j { #← this line was changed
if $i %% $j {
$sum += $j;
}
}
if $sum >= $max {
$max = $sum;
$x = $i;
}
}
say “$x $max”;
Code (Python)
#!/usr/bin/env python3
a = int(input())
b = int(input())
_max = 0
for i in range(a, b + 1):
_sum = 0
for j in range(1, i + 1):
if i % j == 0:
_sum += j
if _sum >= _max:
_max = _sum
x = i
print(x, _max)
Code (Rust)
use std::io;
fn main() {
let mut input_line1 = String::new();
let mut input_line2 = String::new();
io::stdin().read_line(&mut input_line1).expect("Failed to read a");
let a: u32 = input_line1.trim().parse().expect("a is not an integer");
io::stdin().read_line(&mut input_line2).expect("Failed to read b");
let b: u32 = input_line2.trim().parse().expect("b is not an integer");
let mut max = 0;
let mut x = 0;
for i in a..=b {
let mut sum = 0;
for j in 1..=i {
if i % j == 0 {
sum += j;
}
}
if sum >= max {
max = sum;
x = i;
}
}
println!("{x} {max}");
}
Welcome to Rakudo™ v2022.12-1-gd52342eb0.
Implementing the Raku® Programming Language v6.d.
Built on MoarVM version 2022.12.