Nikita Volkov

Profiling in Haskell can be an overwhelmingly confusing task. There’s plenty of little things you need to set up right to be able to perform it. This post aims to organize this information.

Summary

The project must be configured with profiling enabled.

Some specific options must be set when configuring the profiling executable in the “.cabal” file.

All the project’s dependencies must be installed with profiling enabled.

Configuring the project

Well, there’s nothing tricky here. All you need to do is just pass the --enable-library-profiling and --enable-executable-profiling flags to the configure task. E.g., here is how you configure a project to support profiling as well as running tests and benchmarks:

Explanation of the runtime settings:

-N sets the number of available processors for the executable to be equal to the amount of processors on the running system. Otherwise it’s just 1.

-p generates a time and allocation profiling report in a “.prof” file. Details here.

-s outputs a report on garbage collection.

-h generates a standard report on memory usage. Which can then be used to produce a plot in a postscript file using the “hp2ps” utility. Details here.

-i0.1 sets the sampling frequency of memory profiling to every tenth of a second.

Installing the dependencies

This gets trickier. Chances are, most of your dependencies were installed without profiling support and you need to reinstall them. Haskell package management has never been much friendly and it will require you to either drop the whole local packages’ DB and reinstall all the dependencies with profiling enabled, or manually reinstall them all one by one.

Fortunately, since the version 1.17 Cabal comes with a “sandboxes” feature, which maintains an isolated dependencies DB per each project. This is a workaround for numerous Haskell package management issues and is a way to go for us. So before continuing please make sure that you have a proper version of Cabal.

Initialize the project’s sandbox:

cabal sandbox init

Install the dependencies with support for profiling:

cabal install --only-dependencies --enable-library-profiling

Alternatively you can add a “cabal.config” file to the root of your project with the following line:

library-profiling: True

This will ensure that all the dependencies you install with this project will be with support for profiling. So now you can simply run the following:

cabal install --only-dependencies

Running

With all things set up you can finally run your profiling configuration with the following: