loading...
Cover image for Profiling Rust code on Windows using CodeXL

Profiling Rust code on Windows using CodeXL

martinmodrak profile image Martin Modrák ・4 min read

I like the Rust language. However, developing with Rust on Windows currently has a lot of rough edges. One thing I was struggling with was a working solution for profiling Rust code on Windows.
In the end, the best tool for the job I found was CodeXL (formerly known as AMD CodeXL). Here is a step-by-step tutorial on how it is done.
The tutorial was tested on Windows 10 with Rust 1.14.0.

Note on Debugging and Targets

To be able to debug the code I use the x86_64-pc-windows-gnu target (as opposed to x86_64-pc-windows-msvc which is the default for Windows).
However, the profiling experience is better with the MSVC target. So maybe the best approach is to switch between the targets based on your current needs using rustup:

> rustup default stable-x86_64-pc-windows-msvc
> rustup default stable-x86_64-pc-windows-gnu

An aside on debugging on Windows. If you want to setup Rust debug environment on Windows, I recommend Sherry Ummen's tutorial for
setting up Rust + Visual Studio Code (requires the GNU target).
I've heard good rumours about Rust support in Sublime and Atom, but have yet to test it myself.
AFAIK the debugging support in the Visual Studio 2015 extension is fairly limited and also requires the GNU target.

UPDATE: In theory, you should be able to use standard debugger and profiler of Visual Studio (with the C++ toolset) to analyze code compiled with the MSVC target. I tried attaching Visual Studio debugger to a running Rust process (compiled with debug information) and it worked nicely! I was however unable to make the profiler work with the exact same program. I'll write another tutorial if I figure it out.

Profiling

First thing we need to do is to compile the program optimized (otherwise profiling makes no sense), but with debugging information:

`

rustc -g -O -o rna.exe ..\src\main.rs
`

If you compile through Cargo, you should be able to set the necessary options by modifying the [profile.release] section of Cargo.toml file. See the docs for more details.

Now open CodeXL. I have tested with version 1.9 and 2.2, but I believe other versions would work as well.

First you switch to profile mode ( Profile -> Switch to Profile Mode):

Switch to profile mode

My app was running pretty long, so I chose the easy path, started the app from command line and used Profile -> Attach to process.

Attach to process

It should be possible to have CodeXL start the app for you, but I didn't bother.

Then you end the profiling by clicking the stop button.

Stop profiling

And you get the output:

Profile output

As you can note, there are only two functions in the profiling output. That's not because my app has no functions, but because Rust inlined all the rest.

This is the moment, when the GNU target bites you. If you compiled to GNU target, double-clicking on a function shows the actual time spent in individual processors instructions, but I found no simple way to match those instructions with the Rust code (and the inlined functions).

Function detail - GNU target

On the other hand, if you use the MSVC target, you see the actual source code!

Function detail - MSVC target

However, even with MSVC, all samples attributed to an inlined function are associated with the line where the function is called, so you still see very little detail.
To take the example above: is the next_cut() function really consuming so many samples or is the match statement responsible?

So I did a little trick, that gives me more information, but may add noise to the timings. I forced the compiler to not inline anything:

`

rustc -g -O -C inline-threshold=0 -o rna.exe ..\src\main.rs
`

Which gives a more helpful result:

Results - without inlining

I can now be quite confident that most of the time is spent in the actual body of main and find_next_cut and not in the inlined functions.

I also tried the Very Sleepy profiler, which seemed to sort of work,
but I could not get it to display any debug information (especially the function names).

Hope this helps you!

Posted on by:

martinmodrak profile

Martin Modrák

@martinmodrak

Reasearcher/programmer, currently doing bioinformatics at Czech Academy of Sciences. PhD in AI for videogames.

Discussion

markdown guide