From 27a0a85e2b19330c0e9dd40e1acbc1c4ce9ac3fe Mon Sep 17 00:00:00 2001 From: VCB Ferreira Date: Sun, 2 Aug 2026 16:47:28 +0200 Subject: [PATCH] added FlameGraph run script --- .gitignore | 5 +++ CMakeLists.txt | 2 +- nufi/parameters.h | 4 +- run | 103 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 3 deletions(-) create mode 100755 run diff --git a/.gitignore b/.gitignore index bf17354..5d6529f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,8 @@ saved_sims/ .todo-txt/ Notes/ + +*.data +*.perf +*.folded +*.svg diff --git a/CMakeLists.txt b/CMakeLists.txt index 36fd98b..f60d756 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,4 +54,4 @@ target_link_libraries(nufi_poisson deal_ii_setup_target(nufi_poisson) -target_compile_options(nufi_poisson PRIVATE -O3) +target_compile_options(nufi_poisson PRIVATE -O3 -g) diff --git a/nufi/parameters.h b/nufi/parameters.h index cd8eeea..eb6ccb2 100644 --- a/nufi/parameters.h +++ b/nufi/parameters.h @@ -14,7 +14,7 @@ constexpr double X_DOMAIN_RIGHT = 4 * M_PI; constexpr double LX = std::abs(X_DOMAIN_RIGHT - X_DOMAIN_LEFT); constexpr double LX_INV = 1 / LX; -constexpr size_t CALC_NX = 256; +constexpr size_t CALC_NX = 512; constexpr double CALC_DX = LX / CALC_NX; constexpr double V_DOMAIN_LEFT = -10.; @@ -28,7 +28,7 @@ constexpr double DV = std::abs(V_DOMAIN_RIGHT - V_DOMAIN_LEFT) / NV; // 1 -> landau-damping // 2 -> maxwellian // 3 -> bump-on-tail -constexpr size_t f0_TYPE = 0; +constexpr size_t f0_TYPE = 1; // deal.ii options constexpr unsigned int GLOBAL_REFINEMENT = 7; diff --git a/run b/run new file mode 100755 index 0000000..24dfed8 --- /dev/null +++ b/run @@ -0,0 +1,103 @@ +#!/usr/bin/env bash +# +# profile_flamegraph.sh +# +# Runs ./build/nufi_poisson under `perf record`, then converts the +# result into a flamegraph. Run this from the project root ("."). +# +# All profiling artifacts are written to ./results/perf/ so they don't +# collide with the simulation's own output files in ./results/ +# (nufi_poisson clears regular files in "results/" at the start of +# main(), see main.cc's clear_results_directory()). + +set -euo pipefail + +# ---- config ----------------------------------------------------------- +BINARY="./build/nufi_poisson" +FLAMEGRAPH_DIR="${HOME}/.local/bin/FlameGraph" +OUT_DIR="./results/perf" +PERF_FREQ=99 + +# ---- checks ------------------------------------------------------------- +if [[ ! -x "${BINARY}" ]]; then + echo "error: ${BINARY} not found or not executable. Build the project first." >&2 + exit 1 +fi + +if [[ ! -x "${FLAMEGRAPH_DIR}/stackcollapse-perf.pl" ]] || [[ ! -x "${FLAMEGRAPH_DIR}/flamegraph.pl" ]]; then + echo "error: FlameGraph scripts not found under ${FLAMEGRAPH_DIR}" >&2 + exit 1 +fi + +if ! command -v perf >/dev/null 2>&1; then + echo "error: 'perf' not found on PATH." >&2 + exit 1 +fi + +# perf needs kernel.perf_event_paranoid low enough to record kernel symbols +# and full call graphs. -1 is fully open; most distros default to 1-4. +# This only sets it for the current boot (same effect as writing directly +# to /proc/sys/kernel/perf_event_paranoid) -- it does NOT persist, and does +# NOT touch /etc/sysctl.conf. Override the target with: +# PERF_EVENT_PARANOID=0 ./profile_flamegraph.sh +PARANOID_PATH="/proc/sys/kernel/perf_event_paranoid" +DESIRED_PARANOID="${PERF_EVENT_PARANOID:--1}" + +if [[ -r "${PARANOID_PATH}" ]]; then + CURRENT_PARANOID="$(cat "${PARANOID_PATH}")" + if [[ "${CURRENT_PARANOID}" -gt "${DESIRED_PARANOID}" ]]; then + echo "==> kernel.perf_event_paranoid is ${CURRENT_PARANOID}, lowering to ${DESIRED_PARANOID} (needs sudo) ..." + if ! sudo sysctl -w "kernel.perf_event_paranoid=${DESIRED_PARANOID}" >/dev/null; then + echo "warning: could not lower kernel.perf_event_paranoid -- kernel symbols/call graphs may be incomplete." >&2 + echo " you can set it manually with: sudo sysctl -w kernel.perf_event_paranoid=${DESIRED_PARANOID}" >&2 + fi + fi +fi + +mkdir -p "${OUT_DIR}" + +PERF_DATA="${OUT_DIR}/perf.data" +PERF_SCRIPT_OUT="${OUT_DIR}/out.perf" +FOLDED_OUT="${OUT_DIR}/out.folded" +FLAMEGRAPH_OUT="${OUT_DIR}/flamegraph.svg" + +# ---- run ---------------------------------------------------------------- +echo "==> Recording with perf (-F ${PERF_FREQ}) ..." +echo " (Ctrl+C stops the binary early and still runs the rest of the pipeline)" + +# perf record catches SIGINT itself, finalizes perf.data, and exits -- but +# bash's default non-interactive behavior is to terminate the *script* the +# moment it sees SIGINT, and `set -e` would abort on perf record's non-zero +# exit status anyway. Temporarily ignore SIGINT at the script level and +# capture the exit code manually so an early Ctrl+C just moves on to +# generating the flamegraph from whatever was captured. +set +e +trap '' SIGINT +perf record -F "${PERF_FREQ}" -g -o "${PERF_DATA}" -- "${BINARY}" +PERF_EXIT=$? +trap - SIGINT +set -e + +if [[ ${PERF_EXIT} -ne 0 ]]; then + echo " (perf record exited with code ${PERF_EXIT}, likely from an interrupt -- continuing anyway)" +fi + +if [[ ! -s "${PERF_DATA}" ]]; then + echo "error: ${PERF_DATA} is missing or empty, nothing to process." >&2 + exit 1 +fi + +echo "==> Generating perf script output ..." +perf script -i "${PERF_DATA}" > "${PERF_SCRIPT_OUT}" + +echo "==> Collapsing stacks ..." +"${FLAMEGRAPH_DIR}/stackcollapse-perf.pl" "${PERF_SCRIPT_OUT}" > "${FOLDED_OUT}" + +echo "==> Building flamegraph ..." +"${FLAMEGRAPH_DIR}/flamegraph.pl" "${FOLDED_OUT}" > "${FLAMEGRAPH_OUT}" + +echo "==> Done." +echo " perf.data : ${PERF_DATA}" +echo " out.perf : ${PERF_SCRIPT_OUT}" +echo " out.folded : ${FOLDED_OUT}" +echo " flamegraph : ${FLAMEGRAPH_OUT}"