Tools for profiling Rust

14 Sep 2016

The first time I needed to profile a Rust application I came across Llogiq’s post - Profiling Rust applications on Linux. This post was incredibly helpful to me and succeeded in getting me off the ground. After spending a little more time with Rust and needing to do a little more profiling I’ve discovered a few alternatives that I think make valuable additions. In this post I’ll be writing about these in the hope that someone else may stumble upon it and get off the ground.

This post is only relevant for profiling on Linux - though the cpuprofiler introduced may work on any unix system.

Llogiq’s post remains a very valuable resource and you should probably read it if you are planning on profiling.

What is profiling?

We use profiling to measure the performance of our applications - generally in a more fine-grained manner than benchmarking alone can provide. In fact, often with profiling we can reveal slow areas of code that we may not have suspected at all.

To build a profile we monitor the application as it runs and record various information. For example, cpu cache misses or total instructions within a function. This is a complicated task but fortunately there are a number of tools available to us - some of which are discussed in Llogiq’s blog post.

In this post I’ll talk about some alternatives and more recent developments that make profiling Rust applications a little easier.

Cpuprofiler is a new library which provides bindings to google’s gperftools cpu profiler. The profiler is a statistical sampling profiler - which means that it records the function stack information at set intervals. This technique generally has a lower overhead than instrumentation profilers like valgrind.

But the real winning points for me were the powerful output formats from this profiler and the ability to profile only chosen sections of code.

How do I use it?

Install gperftools (which includes the cpu profiler).

Link to cpuprofiler in your Cargo.toml manifest

[dependencies]
cpuprofiler = "0.0.2"

start and stop the profiler around the code you’d like to profile.

usecpuprofiler::PROFILER;// Unlock the mutex and start the profilerPROFILER.lock().unwrap().start("./my-prof.profile").expect("Couldn't start");// Code you want to sample goes here!neuralnet.train(&inputs,&targets);// Unwrap the mutex and stop the profilerPROFILER.lock().unwrap().stop().expect("Couldn't stop");

The gperftools library only allows one profiler to be active at any time and so we capture this by making PROFILER a static Mutex<Profiler>.

Or we can use graphviz to get an interactive graph. You should be able to pan and zoom on the svg below.

And pprof provides a bunch of other options that I haven’t tried yet - like profile comparisons. It’s also probable that the outputs from
the newer version of pprof is even nicer!

Summary

I’ve briefly discussed two tools which weren’t covered (didn’t exist) in the previously linked post. I believe they start to provide a more
compelling story for profiling Rust - though of course there is still a way to go.

I have only tested the above on linux - though supposedly cpuprofiler will work on any unix system.

In the future I’d love to try and get a simple statistical sampling profiler working in Rust (using libbacktrace). I’m certainly no expert and if anyone has any pointers on doing this I’d love to hear them.

Providing support within cargo-profiler for cpuprofiler would be a cool addition (I think!).