The runtime performance of Rust for a simple path tracer

In my last article I described my port of smallpt to Rust.

In this short post I’m updating with some performance figures. I’m really impressed; the Rust version really is as good as the C++ version! I tested on my home server, a 4-core 2.5GHz X3323, which was otherwise idle.

Due to some stack limitations in Rust, the Rust code bails out after 500 levels of recursion; so I modified smallpt to do the same.

I ran smallpt like this:

$ g++ -O3 -ffast-math -march=native -fopenmp smallpt.c \ && time ./a.out 1024 Rendering (1024 spp) 100.00% real 13m5.357s user 51m56.112s sys 0m0.303s

And then I ran the rust code with:

$ cargo build --release \ && time cargo run --release -- -s 1024 Compiling path_tracer v0.1.0 (file:///home/matthew/path-tracer) Running `target/release/path_tracer -s 1024` Using 4 threads Rendering (1024 spp) 99.8698%... Writing output to 'image.ppm' real 12m53.603s user 51m17.749s sys 0m0.323s

The two output images are similar enough that I’m pretty sure I’m running them with equivalent settings:



The output of the Rust version.



The output of the C++ version.

Pretty impressive: the Rust version is actually a tiny bit faster that the C++ version. I double-checked that both the Rust and C++ version use all the CPUs on the machine too. If anything, the C++ compiler settings I used are more generous than those the LLVM backend is using for Rust!

Now I just need to get my head around how the borrow checker works: I had some great suggestions on the Rust subreddit but have been unable to get the borrow checker to let me use them.

I plan on hacking more on the tracer, but I know myself too well to promise anything. I’ve had a bunch of suggestions for zindex (which I must blog about very soon), Seasocks and of course GCC Explorer and I will probably spend some time on them. But you can’t really beat the awesome feedback of working on a renderer!