What can I improve in this code?


#1

Hello.

I was testing some code in different programming languages, just seeing which is more readable, with less LOC and maybe faster. The languages are C++, Rust and Go.

I think I made some mistake (I’m learning rust, so the test itself is not to consider which language is better, I’m just doing some simple comparisions), because even with inline optimization (In fact, the performance got worst with it) the Rust version is much slower than C++'s.

The test is the “fibonacci result” of 45. The results are:
Go: 12.096s
Rust: 9.056s
C++ : 3.685s

So, am I doing it “wrong”? (maybe there’s some idiomatic way to code this, I missed some important optimization or maybe there’s no way it can be faster at all…?).

Rust version: http://pastebin.com/PhVieAkr
C++ version: http://pastebin.com/sAxzkMak

Thanks in advance.


#2

No, it just looks like gcc optimizes this better. It probably unrolls it a bit but I haven’t looked at the assembly.

If you compile it with clang instead (which uses LLVM like rustc) the runtimes are the same.


#3

Thanks for the reply. Clang’s binary is slower indeed. Almost the same time as Rust’s. I thought that clang (the llvm backend) produced good binaries (if not better than GCC), I didn’t know LLVM has such issue.


#4

LLVM’s results are often competitive with GCC (and both change all the time with each new version released). You can’t really judge a compiler using a single microbenchmark.


#5

Yes, of course. I’m just testing things sporadically. I don’t need the fastest language/compiler and such. I don’t even use math in my projects. Well, the fibonacci test is often used to do simple benchmarks, I tested (even considering that I’m sure about learning Rust) the code and was surprised, since I’m new in rust (and other benchmarks/test I have seen show clang’s binary as fast as gcc’s) I thought there was something wrong with my implementation. :smile:

As I think more about it, it doesn’t seem that surprising. Gcc is older, with a wider range of users, so it’s more stable and such


#6

Just an idea: Try using “if num < 2” instead of match in the rust code .


#7

Why would that be better?


#8

Is someone working on an alternative grc Rust compiler with the same gcc back-end? (For D language there are three compilers).


#9

Thanks. Well, I tried, but no notable performance difference, so I used the most readable option


#10

Why would that have any performance difference? I bet they are compiled to the same binary.


#11

Well, they’re not. See below the assembly code for gcc, clang and rustc. I don’t know why, but for some things gcc still generate better code. The same source file, same flags, different compilers:

lazpeng:~/workspace $ time binaries/testcpp_gcc
1134903170

real    0m3.344s
user    0m3.332s
sys     0m0.004s
lazpeng:~/workspace $ time binaries/testcpp_clang
1134903170

real    0m9.219s
user    0m9.208s
sys     0m0.004s

rustc assembly: http://pastebin.com/CnesmGju
g++ assembly: http://pastebin.com/kK89SR87
clang++ assembly: http://pastebin.com/BAp9zXSR


#12

I mean there’s no difference in performance between using match num with 0 | 1 and if num < 2. Here’s the playground (choose “Release”, then “ASM”). And here’s the comparison of the functions – only the names differ.

That gcc currently generates better code than clang is another topic – and a room for improvement.


#13

I haven’t looked in detail but it looks like gcc (as it knows the input value) unrolls the loop. Add an attribute with no inline (I think it’s something like this __attribute__ ((noinline)); on the function declaration or move the code to a separate file to prevent the compiler from knowing the size.

you can also do something like

extern int foo;

void main() {
  function(foo);
}

This code will not link but you can compile it, look at the disassembly because the compiler cant make assumptions about the size anymore.


#14

Oh, ok. I’m new to the forum’s reply system