mirror of
https://github.com/torvalds/linux.git
synced 2026-11-10 17:11:02 +01:00
Port stackcollapse.py from tools/perf/scripts/python/ to a standalone script in tools/perf/python/ refactored into a StackCollapseAnalyzer class. Improvements compared to the legacy script: - Traverse sample.callchain directly from perf.session without allocating per-event dictionaries, and fall back to sample.symbol when a sample has no callchain. - Replace deprecated optparse with argparse, adding -i/--input alongside --include-tid, --include-pid, --no-comm, --tidy-java, and --kernel. - Handle BrokenPipeError cleanly when output is piped into downstream tools (such as head or flamegraph.pl). Add a shell test (test_stackcollapse_python.sh) using a CPU workload (perf test -w noploop) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
79 lines
2.0 KiB
Bash
Executable File
79 lines
2.0 KiB
Bash
Executable File
#!/bin/bash
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
# stackcollapse python test
|
|
|
|
set -e -o pipefail
|
|
|
|
shelldir=$(dirname "$0")
|
|
# shellcheck source=lib/setup_python.sh
|
|
. "${shelldir}"/lib/setup_python.sh
|
|
|
|
if ! "$PYTHON" -c 'import perf' > /dev/null 2>&1; then
|
|
echo "Skipping test, perf python module not found"
|
|
exit 2
|
|
fi
|
|
|
|
script_dir="$(dirname "$0")/../../python"
|
|
script_path="${script_dir}/stackcollapse.py"
|
|
|
|
if [ ! -f "$script_path" ]; then
|
|
echo "Skipping test, stackcollapse.py not found at $script_path"
|
|
exit 2
|
|
fi
|
|
|
|
err=0
|
|
temp_data=""
|
|
temp_out=""
|
|
|
|
cleanup() {
|
|
rm -f "${temp_data}" "${temp_out}"
|
|
}
|
|
trap 'cleanup' EXIT TERM INT
|
|
|
|
temp_data=$(mktemp /tmp/perf.data.XXXXXX)
|
|
temp_out=$(mktemp /tmp/perf.out.XXXXXX)
|
|
|
|
echo "Testing stackcollapse.py..."
|
|
|
|
# Create a perf.data file with callchains. Use a busy workload rather than
|
|
# sleep, as an idle system may not generate any samples at all.
|
|
perf record -g -o "${temp_data}" \
|
|
-- perf test -w noploop >/dev/null 2>&1 || \
|
|
{ echo "Skipping test, perf record failed"; exit 2; }
|
|
|
|
if [ ! -s "${temp_data}" ]; then
|
|
echo "Skipping test, perf record failed to create data"
|
|
exit 2
|
|
fi
|
|
|
|
# Check that the script executes with default options
|
|
if ! "$PYTHON" "$script_path" -i "${temp_data}" > "${temp_out}"; then
|
|
echo "stackcollapse.py test failed"
|
|
err=1
|
|
else
|
|
# It outputs stacks like: swapper;...;... 2
|
|
if [ ! -s "${temp_out}" ]; then
|
|
echo "Expected stack traces in output, but output is empty."
|
|
err=1
|
|
else
|
|
echo "stackcollapse default test passed."
|
|
fi
|
|
fi
|
|
|
|
# Test CLI flags (--include-pid, --include-tid, --tidy-java, --kernel) and BrokenPipeError
|
|
if ! "$PYTHON" "$script_path" -i "${temp_data}" \
|
|
--include-pid --include-tid --tidy-java --kernel | head -n 1 > "${temp_out}" || \
|
|
[ ! -s "${temp_out}" ]; then
|
|
echo "stackcollapse.py options/pipe test failed"
|
|
err=1
|
|
elif ! "$PYTHON" "$script_path" -i "${temp_data}" --no-comm > "${temp_out}" || \
|
|
[ ! -s "${temp_out}" ]; then
|
|
echo "stackcollapse.py --no-comm test failed"
|
|
err=1
|
|
else
|
|
echo "stackcollapse options test passed."
|
|
fi
|
|
rm -f "${temp_out}"
|
|
|
|
exit $err
|