Running Valgrind with a Custom Runner
By default, Gungraun invokes Valgrind directly to run your benchmarks. However,
if Valgrind is not available on your host system, you can use the
--valgrind-runner option to run Valgrind through a container or alternative
execution environment.
This is controlled by several command-line options and their respective environment variables:
--valgrind-runner(env:GUNGRAUN_VALGRIND_RUNNER): Specify the runner executable. This can be anything from a script todocker,sudo, ...--valgrind-runner-args(env:GUNGRAUN_VALGRIND_RUNNER_ARGS): Pass additional arguments to the runner (supports environment variable interpolation)--valgrind-bin(env:GUNGRAUN_VALGRIND_BIN): Specify the Valgrind executable path.--valgrind-runner-dest(env:GUNGRAUN_VALGRIND_RUNNER_DEST): Override the destination directory of Valgrind output files--valgrind-runner-root(env:GUNGRAUN_VALGRIND_RUNNER_ROOT): Override the path to the workspace root directory
The command-line options take precedence over environment variables.
If using a custom runner, the custom runner is responsible for a stable benchmark runtime environment:
- clear the environment variables
- disable ASLR, if asked to do so
- if
--valgrind-runner-rootor--valgrind-runner-destare used, to create these directories - eventually run Valgrind to create the output files. Failing to produce the output files will fail the benchmark.
How Gungraun Invokes the Runner
When a custom runner is specified, Gungraun invokes it as follows:
<RUNNER> [RUNNER_ARGS] <VALGRIND_BIN> [VALGRIND_ARGS] <BENCHMARK> [BENCHMARK_ARGS]
Key points:
<RUNNER_ARGS>are additional arguments for the runner from--valgrind-runner-args<VALGRIND_BIN>is the resolved path to Valgrind (from--valgrind-binor system default)- Your normal
<VALGRIND_ARGS>for example set with--callgrind-args,--cachegrind-args, etc. are passed through to Valgrind after the runner - The benchmark binary is passed as Valgrind's first positional argument. After that all arguments to the benchmark binary are added as last arguments.
- All paths set by Gungraun in the Valgrind arguments are absolute paths
- Environment variables are still cleared by default. Configure this behavior
with
LibraryBenchmarkConfigorBinaryBenchmarkConfigin the benchmarks or in the CLI with--env-clear(env:GUNGRAUN_ENV_CLEAR)
Environment Variables for Runners
Gungraun sets the following environment variables for the custom Valgrind runner process even if the environment variables have been asked to be cleared. The custom Valgrind runner is responsible for clearing the environment variables.
GUNGRAUN_VR_DEST_DIR: Destination directory for output filesGUNGRAUN_VR_HOME: The gungraun home directoryGUNGRAUN_VR_WORKSPACE_ROOT: The project's workspace root directoryGUNGRAUN_ALLOW_ASLR:yesornobased on--allow-aslrsetting
These can be interpolated in --valgrind-runner-args like any other environment
variable using the ${VAR} syntax.
Passing Additional Arguments
Use --valgrind-runner-args to pass additional arguments to your wrapper:
cargo bench -- \
--valgrind-runner=~/bin/docker-valgrind \
--valgrind-runner-args='--volume=/my/project:/project:ro'
Environment Variable Interpolation
The --valgrind-runner-args option supports environment variable interpolation
using the ${VAR} syntax. Variables are resolved in this order:
GUNGRAUN_VR_*variables set by Gungraun andGUNGRAUN_ALLOW_ASLR- Variables specified via
--envsand in the benchmark with aLibraryBenchmarkConfigorBinaryBenchmarkConfig - System environment variables. This happens before the environment variables
are cleared, so all environment variables passed to the
cargo benchinvocation are available for interpolation.
This allows passing dynamic configuration to your runner:
cargo bench -- \
--valgrind-runner=./docker-wrapper \
--valgrind-runner-args='--allow-aslr=${GUNGRAUN_ALLOW_ASLR} --dest=${GUNGRAUN_VR_DEST_DIR}'
Path Substitution
When running in containers, paths on the host may differ from paths inside the
container. Use these options to help the runner use the correct directories and
files. If using docker as custom runner, then most likely you will need to
specify all of them. Note that Gungraun doesn't create any directories given by
--valgrind-runner-dest and --valgrind-runner-root. It is your responsibility
to create these directories before the first custom runner execution.
--valgrind-runner-dest
Specifies a path prefix that replaces all occurrences of the value of
GUNGRAUN_VR_DEST_DIR in the Valgrind command line arguments. Useful when using
a container volume mount that is different from the destination directory on the
host. The destination directory on the host is guaranteed to be different for
each benchmark and Valgrind runner execution, so it is safe to mount the
original GUNGRAUN_VR_DEST_DIR to the same directory for each invocation.
However, make sure you have write permissions to that directory and it is empty
before the first invocation of the custom Valgrind runner.
Warning Setting this variable to a non-empty directory or to a directory which contains important data will potentially destroy the contained data. Gungraun repeatedly dumps files in this directory and then either deletes all of the contained files or moves all content to the final destination directory on the host.
If the directory /tmp/dest in the docker container exists:
cargo bench -- \
--valgrind-runner=docker \
--valgrind-runner-dest=/tmp/dest
--valgrind-runner-args='run --volume ${GUNGRAUN_VR_DEST_DIR}:/tmp/dest alpine'
--valgrind-runner-root
Specifies a path prefix that replaces all occurrences in paths with the value of
GUNGRAUN_VR_WORKSPACE_ROOT in the Valgrind command line arguments. Useful when
a container mount of the workspace root is different from the host workspace
root. When running library benchmarks, the compiled benchmark binary (somewhere
located in ${GUNGRAUN_VR_WORKSPACE_ROOT}/target/release/deps/some_name-1a2b3c)
needs to be executed in the container which you could achieve with something
similar to:
cargo bench -- \
--valgrind-runner=docker \
--valgrind-runner-root=/workspace
--valgrind-runner-args='run --volume ${GUNGRAUN_VR_WORKSPACE_ROOT}:/workspace alpine'
Running Valgrind in a Container
Docker/Podman Example
Note: You'll need a Docker image with Valgrind installed. For example:
FROM ubuntu:24.04 RUN apt-get update && \ apt-get install -y libc6-dbg valgrind && \ mkdir -p /workspace /var/gungraun-destBuild and tag the image:
docker build -t valgrind-image .
Then use it with Gungraun and execute the following in your workspace root (the
directory with the top-level Cargo.toml file). Here, --valgrind-bin points
to the Valgrind executable in the container although the path might be the same
on the host:
cargo bench -- \
--clear-env=no \
--valgrind-runner=docker \
--valgrind-bin=/usr/bin/valgrind \
--valgrind-runner-root=/workspace \
--valgrind-runner-dest=/var/gungraun-dest \
--valgrind-runner-args='run --unsetenv-all' \
--valgrind-runner-args='-v ${GUNGRAUN_VR_WORKSPACE_ROOT}:/workspace' \
--valgrind-runner-args='-v ${GUNGRAUN_VR_DEST_DIR}:/var/gungraun-dest' \
--valgrind-runner-args='valgrind-image'
--clear-env=no is set, since docker needs some of the environment variables
and we can configure docker with --unsetenv-all to clear the environment
variables for the container.