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!
Matt Godbolt is a C++ developer living in Chicago. Follow him on Mastodon or Bluesky.