diff --git a/Cargo.toml b/Cargo.toml index 85d174f6..4d91f041 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -109,6 +109,8 @@ arraystring = "0.3.0" criterion = "0.5.1" filepath = "0.1.2" filetime = "0.2.23" +# XXX: `flamegraph` fails to build, MSRV 1.74 +# flamegraph = "0.6.5" jetscii = "0.5.3" memchr = "2.7.2" test-case = "3.3.1" @@ -120,13 +122,24 @@ test-case = "3.3.1" codegen-units = 1 panic = "abort" strip = true +lto = true [profile.flamegraph] -# XXX: requires manual install of `flamegraph` -# not added to `dev-dependencies` due to MSRV 1.70.0 inherits = "release" codegen-units = 16 +debuginfo = 2 +lto = false panic = "unwind" +split-debuginfo = "unpacked" +strip = false + +[profile.valgrind] +inherits = "release" +codegen-units = 16 +debuginfo = 2 +lto = false +panic = "abort" +split-debuginfo = "unpacked" strip = false # other helpful development tools diff --git a/tools/heaptrack.sh b/tools/heaptrack.sh index e4fb1094..88113056 100755 --- a/tools/heaptrack.sh +++ b/tools/heaptrack.sh @@ -30,7 +30,12 @@ if ! which flamegraph.pl &>/dev/null; then exit 1 fi -declare -r BIN=./target/release/s4 +echo -e "Requires building with \e[1m-g\e[0m + RUSTFLAGS=-g cargo build --profile valgrind +" >&2 +sleep 1 + +declare -r BIN=./target/valgrind/s4 declare -r BIN_TARGET=s4 NOTES=$("${BIN}" --version | head -n1) declare -r OUT=heaptrack.${BIN_TARGET}.data diff --git a/tools/valgrind-callgrind.sh b/tools/valgrind-callgrind.sh index 7e409a12..448b9929 100755 --- a/tools/valgrind-callgrind.sh +++ b/tools/valgrind-callgrind.sh @@ -12,6 +12,8 @@ # User may set environment variable $PROGRAM. # Passed arguments are passed to $PROGRAM and override default arguments. # +# build the program with `--profile valgrind` +# set -euo pipefail @@ -31,29 +33,59 @@ if ! callgrind=$(which callgrind_annotate); then exit 1 fi -declare -r PROGRAM=${PROGRAM-./target/release/s4} +declare -r PROGRAM=${PROGRAM-./target/valgrind/s4} + +if [[ ! -x "${PROGRAM}" ]]; then + echo "PROGRAM does not exist '${PROGRAM}'" >&2 + echo "build with:" >&2 + echo " RUSTFLAGS=-g cargo build --profile valgrind" >&2 + exit 1 +fi + +if [[ ! -r gprof2dot.py ]]; then + echo "Unable to find gprof2dot.py" >&2 + echo "run:" >&2 + echo "wget 'https://raw.githubusercontent.com/jrfonseca/gprof2dot/2024.06.06/gprof2dot.py'" >&2 + exit 1 +fi (set -x; uname -a) (set -x; git log -n1 --format='%h %D') (set -x; "${PROGRAM}" --version) +(set -x; dot -V) (set -x; "${valgrind}" --version) | head -n1 +if "${valgrind}" --version | grep -qFe '3.18'; then + echo "ERROR: valgrind 3.18 is known to have issues with rust + see https://nnethercote.github.io/2022/01/05/rust-and-valgrind.html + section 'Missing inline stack frames' + +Compile the latest valgrind: +1. download from https://valgrind.org/downloads/current.html +2. untar +3. cd valgrind +4. ./configure --prefix=/usr/local +5. make +6. sudo make install +" >&2 + exit 1 +fi (set -x; "${callgrind}" --version) || true # --version causes process return code 255 + echo declare -a args=( - -z 0xFFFF -a 20000101T000000 -b 20000101T080000 - ./logs/other/tests/gen-100-10-...... - ./logs/other/tests/gen-100-10-BRAAAP.log - ./logs/other/tests/gen-100-10-FOOBAR.log - ./logs/other/tests/gen-100-10-______.log - ./logs/other/tests/gen-100-10-skullcrossbones.log - ./logs/other/tests/gen-100-4-happyface.log + # ./logs/other/tests/gen-100-10-...... + # ./logs/other/tests/gen-100-10-BRAAAP.log + # ./logs/other/tests/gen-100-10-FOOBAR.log + # ./logs/other/tests/gen-100-10-______.log + # ./logs/other/tests/gen-100-10-skullcrossbones.log + # ./logs/other/tests/gen-100-4-happyface.log ./logs/other/tests/gen-1000-3-foobar.log - ./logs/other/tests/gen-200-1-jajaja.log - ./logs/other/tests/gen-400-4-shamrock.log + # ./logs/other/tests/gen-200-1-jajaja.log + # ./logs/other/tests/gen-400-4-shamrock.log ) if [[ ${#} -ge 1 ]]; then @@ -64,8 +96,13 @@ if [[ ${#} -ge 1 ]]; then done fi -OUT=./callgrind.out -rm -f "${OUT}" +OUT=${OUT-./callgrind} +OUTOUT="${OUT}.out" +OUTDOT="${OUT}.dot" +OUTPNG="${OUT}.png" +OUTSVG="${OUT}.svg" + +rm -f "${OUTOUT}" "${OUTDOT}" "${OUTPNG}" set -x @@ -74,15 +111,23 @@ set -x --collect-bus=yes \ --collect-systime=yes \ `#--separate-threads=yes` \ - --callgrind-out-file="${OUT}" \ + --callgrind-out-file="${OUTOUT}" \ -- \ "${PROGRAM}" \ "${args[@]}" \ >/dev/null -exec \ - "${callgrind}" \ +python gprof2dot.py \ + --format=callgrind \ + --output="${OUTDOT}" \ + "${OUTOUT}" + +dot -T png "${OUTDOT}" -o "${OUTPNG}" + +dot -T svg "${OUTDOT}" -o "${OUTSVG}" + +"${callgrind}" \ --tree=both \ --show-percs=yes \ $(find ./src -xdev -type d -exec echo -n '--include={} ' \;) \ - "${OUT}" + "${OUTOUT}" diff --git a/tools/valgrind-dhat.sh b/tools/valgrind-dhat.sh index 3d5641ef..37ed5cfe 100755 --- a/tools/valgrind-dhat.sh +++ b/tools/valgrind-dhat.sh @@ -24,7 +24,7 @@ if ! valgrind=$(which valgrind); then exit 1 fi -PROGRAM=${PROGRAM-./target/release/s4} +PROGRAM=${PROGRAM-./target/valgrind/s4} (set -x; uname -a) (set -x; git log -n1 --format='%h %D') || true @@ -35,35 +35,34 @@ echo # default arguments for s4 declare -a args=( - -z 0xFFFF -a 20000101T000000 -b 20000101T080000 - ./logs/other/tests/dtf5-3-LF-CR.log - ./logs/other/tests/dtf5-6a.log.gz.tar - ./logs/other/tests/dtf5-6a.log.xz - ./logs/other/tests/dtf7-20-LEVELS.log - ./logs/other/tests/dtf7-20-LEVELS.log - ./logs/other/tests/dtf7-20-LEVELS.log.gz - ./logs/other/tests/dtf7-20-LEVELS.log.old - ./logs/other/tests/dtf7-20-LEVELS.log.old.gz - ./logs/other/tests/dtf7-20-LEVELS.log.tar - ./logs/other/tests/dtf7-20-LEVELS.log.xz - ./logs/other/tests/dtf9d-12x3-37.log - ./logs/other/tests/gen-20-1-🌚🌛🌜🌝.log - ./logs/other/tests/gen-20-1-⚀⚁⚂⚃⚄⚅.log - ./logs/other/tests/gen-100-10-.......log - ./logs/other/tests/gen-100-10-BRAAAP.log - ./logs/other/tests/gen-100-10-FOOBAR.log - ./logs/other/tests/gen-100-10-______.log - ./logs/other/tests/gen-100-10-skullcrossbones.log - ./logs/other/tests/gen-100-10-skullcrossbones.log.gz - ./logs/other/tests/gen-100-10-skullcrossbones.log.xz - ./logs/other/tests/gen-100-10-skullcrossbones.tar - ./logs/other/tests/gen-100-10.tar - ./logs/other/tests/gen-100-4-happyface.log + # ./logs/other/tests/dtf5-3-LF-CR.log + # ./logs/other/tests/dtf5-6a.log.gz.tar + # ./logs/other/tests/dtf5-6a.log.xz + # ./logs/other/tests/dtf7-20-LEVELS.log + # ./logs/other/tests/dtf7-20-LEVELS.log + # ./logs/other/tests/dtf7-20-LEVELS.log.gz + # ./logs/other/tests/dtf7-20-LEVELS.log.old + # ./logs/other/tests/dtf7-20-LEVELS.log.old.gz + # ./logs/other/tests/dtf7-20-LEVELS.log.tar + # ./logs/other/tests/dtf7-20-LEVELS.log.xz + # ./logs/other/tests/dtf9d-12x3-37.log + # ./logs/other/tests/gen-20-1-🌚🌛🌜🌝.log + # ./logs/other/tests/gen-20-1-⚀⚁⚂⚃⚄⚅.log + # ./logs/other/tests/gen-100-10-.......log + # ./logs/other/tests/gen-100-10-BRAAAP.log + # ./logs/other/tests/gen-100-10-FOOBAR.log + # ./logs/other/tests/gen-100-10-______.log + # ./logs/other/tests/gen-100-10-skullcrossbones.log + # ./logs/other/tests/gen-100-10-skullcrossbones.log.gz + # ./logs/other/tests/gen-100-10-skullcrossbones.log.xz + # ./logs/other/tests/gen-100-10-skullcrossbones.tar + # ./logs/other/tests/gen-100-10.tar + # ./logs/other/tests/gen-100-4-happyface.log ./logs/other/tests/gen-1000-3-foobar.log - ./logs/other/tests/gen-200-1-jajaja.log - ./logs/other/tests/gen-400-4-shamrock.log + # ./logs/other/tests/gen-200-1-jajaja.log + # ./logs/other/tests/gen-400-4-shamrock.log ) if [[ ${#} -ge 1 ]]; then