Introduction

So, you wrote an R package containing C++ (or other compiled code) and you want to profile it? Great! Profiling code can help you find bottlenecks in your code that you can look at more closely for further optimization.

I work on Pop!_os, a free Ubuntu based operating system. I am writing this guide to document the steps I took in order to get profiling working for me. There are a few slight differences between what I had to do and what I found online so I hope this is useful.

I listed all the references I used at the bottom of this document.

Install tools

You will need 2 tools. The first is Google’s C++ profiler, gperftools, which you can read about here. The second tool is pprof, which helps you analyze profiling output.

On my Ubuntu-based system, installing gperftools was as simple as using the package manager:

sudo apt-get install google-perftools

If you don’t have graphviz which makes pretty graphs of call traces, you can install that the same way.

Next you need to install pprof which depends on the programming language Go.

sudo apt-get install golang-go
go get github.com/google/pprof

Find where things are

Congratulations, you are now closer to your goal. Now we just need to set some environment variables.

First, it is critical that we can find where the shared object library from perftools is. On most Linux based systems, it seems that it lives in /usr/lib/libprofiler.so. Apparently that’s not the case for Pop!_os. You can use find to figure out where it lives on your machine:

sudo find / -name libprofiler.so

Wherever it is, you now need to make an environment variable with that path:

export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libprofiler.so

Next you need to find where the R binary is. This is used by the profiler to resolve symbols into names of compiled functions used by R. Normally it seems it is located at /usr/lib/R/bin/exec/R. In my case, using this location and firing up the profiler gave me a somewhat frightening error:

cannot find system Renviron
Fatal error: unable to open the base package

In my case the binary was actually located at /usr/lib/R, so the following worked on my machine:

export R_HOME=/usr/lib/R

You can find it from within R by calling R.home().

Profiling your code

Now you’re all ready to go. Assuming you are in a directory containing a R script which calls code you want profilied, say test.R, then you can call:

CPUPROFILE="myprof.log" /usr/lib/R/bin/exec/R -f test.R

Where CPUPROFILE="myprof.log" will create a file myprof.log in the current working directory. You can name it whatever you prefer.

After running your script, it should print normally to the console, but with some line like the following at the end PROFILE: interrupts/evictions/bytes = 3407/1019/588344.

Analysis

To see the results in text format, use pprof:

google-pprof --text /usr/lib/R/bin/exec/R myprof.log | more

To see a graph, just use the -web flag:

google-pprof -web /usr/lib/R/bin/exec/R myprof.log

You will see something like the following:

Enjoy!

References