Profiling
Profiling of generated Rust code
The runrust script has a --flamegraph flag for generating flamegraphs of
the execution time. This gives an overview of the execution time broken down by vertices of the
call graph. While this does not perfectly reflect the number of IR gates
generated by particular functions, it shows where the execution time goes.
This setup has been tested on Ubuntu only (setup instructions below).
Usage
With appropriate setup the usage should be as simple as:
$ ./runrust --flamegraph \
docs/M27-electric-vehicle/ev-inf-mod.zksc \
docs/M27-electric-vehicle/pentagon_inputs/public.json \
docs/M27-electric-vehicle/pentagon_inputs/{instance,witness}_darpa_pentagon.json \
-c docs/M27-electric-vehicle/ev-inf-mod.ccc -o opublic > /dev/null
This call generates file src/Rust/flamegraph.svg that can be viewed with all
modern browsers. Under linux, profile data are gathered with perf and the data
are written to src/Rust/perf.data.
This file can be further transformed and used by other tools like
Firefox profiler. Make sure to have rustfilt
installed. The following line also shortens generated functions names to strip
the internal crate name and unique suffix:
perf script -i src/Rust/perf.data | sed -E 's/zkscc_rust::generated::(.*)_u[[:digit:]]*/\1/g' | rustfilt > zkscc_rust.perf
The file zkscc_rust.perf can be directly loaded into the profile log viewer.
Installing dependencies (Ubuntu)
Install perf and other possible dependencies. Also modify the
kernel.perf_event_paranoid setting to make sure that perf does not have to
be run as root:
sudo apt install linux-tools-common linux-tools-generic linux-tools-`uname -r`
sudo sysctl -w kernel.kptr_restrict=0
sudo sysctl -w kernel.perf_event_paranoid=-1
To make these changes persist reboots, add a file /etc/sysctl.d/50-perf.conf with the following contents:
kernel.kptr_restrict=0
kernel.perf_event_paranoid=-1
Make sure that cargo install directory (usually ~/.cargo/bin) is found in $PATH. Install cargo-flamegraph as user:
cargo install flamegraph
Installing rustfilt is not necessary but it will help demangle function names
to a more readable form:
cargo install rustfilt
Troubleshooting
It's so slow!
The overhead should be less than twice in time.
The issue might be that perf shipped with Ubuntu can be very slow. The solution is to install perf shipped with kernel that is linked against libbfd. We start by installing various dependencies that might be used by perf:
sudo apt install \
flex \
bison \
libelf-dev \
libaudit-dev \
libdw-dev \
libunwind-dev \
python2-dev \
binutils-dev \
libnuma-dev \
libgtk2.0-dev \
libbfd-dev \
libelf1 \
libperl-dev \
libnuma-dev \
libslang2 libslang2-dev \
libunwind8 libunwind8-dev \
binutils-multiarch-dev \
elfutils \
libiberty-dev
The following commands to install perf to ~/.local/bin is for my particular kernel version; substitute your own.
sudo apt install linux-source
cd <some working directory>
cp /usr/src/linux-source-5.15.0/linux-source-5.15.0.tar.bz2 .
tar xvfj linux-source-5.15.0.tar.bz2
cd linux-source-5.15.0/tools/perf
make prefix=$HOME/.local install-bin
Profiling the frontend Haskell code
The simplest way to install the ZK-SecreC compiler frontend with profiling enabled is to invoke stack with appropriate profiling flag:
$ stack install --profile
By default, this installs ZK-SecreC compiler frontend with profiling enabled to ~/.local/bin
directory. Make sure that this directory is found in PATH environment variable.
In order to make the compiler produce profiling output, appropriate flags must be
passed to the Haskell run time system (RTS). For example, to obtain regular
profiling output we must add flag +RTS -p to the original command line call.
After calling
$ zkscc <regular options> +RTS -p
profiling output will be written to a human readable file zkscc.prof.
Heap profiling output is produced with flag -h:
$ zkscc <regular options> +RTS -h
This produces a file zkscc.hp that must be converted to .ps format using
hp2ps utility (should be bundled with GHC).
Much more details about profiling Haskell programs with GHC can be found in the documentation of GHC.