I just wrote a small Rust program to solve an Euler Project problem. We are talking about 29 lines of code. On an Arch Linux system, using Rust 1.6, the compiled executable, compiled with
rustc -O --crate-type bin
is 627KB.
The same program in C is 8.8 KB.
The C version runs in .155 seconds on a Thinkpad X-250. The Rust version is about 3x slower. Given the home-page marketing of "blazingly fast" and the chatter about a leaner runtime system, due to the lack of a GC, I'm more than a bit surprised that the executable is so large. It's almost as big as the executable generated by Gambit Scheme to solve the same problem. The execution speed is also a concern. It doesn't matter in this trivial case, but if that factor-of-3 were to apply to something substantial, it could be a show-stopper.
fn amicable(n:i32) -> i32 {
let dn=d(n);
let ddn=d(dn);
let mut result:i32=0;
if (ddn==n) && (n != dn) {
if n<100000 {
result = result + n;
}
}
result
}
fn d(n:i32) -> i32 {
let mut result:i32 =1;
for m in 2..(n/2+1) {
if (n % m) == 0 {
result = result+m;
}
}
result
}
fn main () {
let mut result:i32=0;
for i in 1..10000 {
result = result + amicable(i);
}
println!("{}", result);
}
Generally the efficiency of Rust is "close" to the efficiency of C code. What's the number for the Euler problem? I suggest to try paste again the Rust code here, because you have lost the formatting. You can also post the C code, for comparison.
fn d(n: i32) -> i32 {
let mut result: i32 = 1;
for m in 2 .. (n / 2 + 1) {
if (n % m) == 0 {
result += m;
}
}
result
}
fn amicable(n: i32) -> i32 {
let dn = d(n);
let ddn = d(dn);
let mut result: i32 = 0;
if ddn == n && n != dn && n < 100_000 {
result += n;
}
result
}
fn main() {
let mut result: i32 = 0;
for i in 1 .. 10_000 {
result += amicable(i);
}
println!("{}", result);
}
I have also translated it to this similar C99 code:
#include <stdio.h>
#include <stdint.h>
int32_t d(const int32_t n) {
int32_t result = 1;
for (int32_t m = 2; m < n / 2 + 1; m++) {
if ((n % m) == 0) {
result += m;
}
}
return result;
}
int32_t amicable(const int32_t n) {
const int32_t dn = d(n);
const int32_t ddn = d(dn);
int32_t result = 0;
if (ddn == n && n != dn && n < 100000) {
result += n;
}
return result;
}
int main() {
int32_t result = 0;
for (int32_t i = 1; i < 10000; i++) {
result += amicable(i);
}
printf("%d\n", result);
return 0;
}
I compile the code with:
rustc -O -C prefer-dynamic test1.rs
gcc -Wall -Wextra -std=c99 -Ofast -flto -s test2.c -o test2
(More aggressive compilation switches don't improve the Rust code run-time).
Using:
gcc 4.9.1
rustc 1.8.0-nightly
My run-times are 0.20 seconds for the Rust code and 0.13 seconds for the C99 code.
On my Windows64 system the binary sizes are 49115 bytes for the Rust exe, and 15872 bytes for the C99 binary.
I tried your -C prefer-dynamic and it appears that Steve is correct -- the executable size is now the same as the C executable -- 8.8KB. Execution time is about .3 seconds, so now approx. a factor of 2 slower than the C version.
Is -C prefer-dynamic documented somewhere? I can't find it, but could have missed it. I do see discussion of the static linking in the book.
Your runtimes and mine are apples and oranges. Different machines, possibly different OSes, libraries, etc. Compare to C on the same machine, compiled with clang, -O3.
Here's my C version:
#include <stdio.h>
#include <stdlib.h>
int d(int n) {
int n_half=n/2, m, result=1;
for (m=2; m<=n_half; m++)
if ((n % m) == 0)
result += m;
return result;
}
int amicable(int n) {
int dn=d(n), ddn=d(dn), result=0;
if ((ddn == n) && (n != dn))
if (n < 10000)
result += n;
return result;
}
int main () {
int i, result=0;
for (i=1; i<10000; i++)
result += amicable(i);
printf("%d\n", result);
exit(0);
}
When iterators avoid you array bound tests, this is reasonable. But in this little program I don't know where the problem is (probably it's worth fixing).
dca@igor:~/Euler/rust$ rustc -O --crate-type bin problem_20.rs
problem_20.rs:14:3: 14:4 error: an inner attribute is not permitted in this context
problem_20.rs:14 #![feature(iter_arith)]
^
problem_20.rs:14:3: 14:4 help: place inner attribute at the top of the module or block
error: aborting due to previous error
So I did as suggested and got this:
dca@igor:~/Euler/rust$ rustc -O --crate-type bin problem_20.rs
problem_20.rs:1:1: 1:24 error: #[feature] may not be used on the stable release channel
problem_20.rs:1 #![feature(iter_arith)]
^~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error