diff options
| author | Namhyung Kim <namhyung@kernel.org> | 2025-11-25 00:07:47 -0800 |
|---|---|---|
| committer | Namhyung Kim <namhyung@kernel.org> | 2025-12-02 16:06:57 -0800 |
| commit | c9cd0c7e529e80e9be79867d2ebb874f67dbc35e (patch) | |
| tree | c1834efa2a497cf58f5618aec58bd7bef6a4d188 /tools/perf/tests/shell/jitdump-python.sh | |
| parent | 25d498e636d1f8d138d65246cfb5b1fc3069ca56 (diff) | |
perf test: Add python JIT dump test
Add a test case for the python interpreter like below so that we can
make sure it won't break again. To validate the effect of build-ID
generation, it adds and removes the JIT'ed DSOs to/from the build-ID
cache for the test.
$ perf test -vv jitdump
84: python profiling with jitdump:
--- start ---
test child forked, pid 214316
Run python with -Xperf_jit
[ perf record: Woken up 5 times to write data ]
[ perf record: Captured and wrote 1.180 MB /tmp/__perf_test.perf.data.XbqZNm (140 samples) ]
Generate JIT-ed DSOs using perf inject
Add JIT-ed DSOs to the build-ID cache
Check the symbol containing the script name
Found 108 matching lines
Remove JIT-ed DSOs from the build-ID cache
---- end(0) ----
84: python profiling with jitdump : Ok
Cc: Pablo Galindo <pablogsal@gmail.com>
Link: https://docs.python.org/3/howto/perf_profiling.html#how-to-work-without-frame-pointers
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Diffstat (limited to 'tools/perf/tests/shell/jitdump-python.sh')
| -rwxr-xr-x | tools/perf/tests/shell/jitdump-python.sh | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/tools/perf/tests/shell/jitdump-python.sh b/tools/perf/tests/shell/jitdump-python.sh new file mode 100755 index 000000000000..ae86203b14a2 --- /dev/null +++ b/tools/perf/tests/shell/jitdump-python.sh @@ -0,0 +1,81 @@ +#!/bin/bash +# python profiling with jitdump +# SPDX-License-Identifier: GPL-2.0 + +SHELLDIR=$(dirname $0) +# shellcheck source=lib/setup_python.sh +. "${SHELLDIR}"/lib/setup_python.sh + +OUTPUT=$(${PYTHON} -Xperf_jit -c 'import os, sys; print(os.getpid(), sys.is_stack_trampoline_active())' 2> /dev/null) +PID=${OUTPUT% *} +HAS_PERF_JIT=${OUTPUT#* } + +rm -f /tmp/jit-${PID}.dump 2> /dev/null +if [ "${HAS_PERF_JIT}" != "True" ]; then + echo "SKIP: python JIT dump is not available" + exit 2 +fi + +PERF_DATA=$(mktemp /tmp/__perf_test.perf.data.XXXXXX) + +cleanup() { + echo "Cleaning up files..." + rm -f ${PERF_DATA} ${PERF_DATA}.jit /tmp/jit-${PID}.dump /tmp/jitted-${PID}-*.so 2> /dev/null + + trap - EXIT TERM INT +} + +trap_cleanup() { + echo "Unexpected termination" + cleanup + exit 1 +} + +trap trap_cleanup EXIT TERM INT + +echo "Run python with -Xperf_jit" +cat <<EOF | perf record -k 1 -g --call-graph dwarf -o "${PERF_DATA}" \ + -- ${PYTHON} -Xperf_jit +def foo(n): + result = 0 + for _ in range(n): + result += 1 + return result + +def bar(n): + foo(n) + +def baz(n): + bar(n) + +if __name__ == "__main__": + baz(1000000) +EOF + +# extract PID of the target process from the data +_PID=$(perf report -i "${PERF_DATA}" -F pid -q -g none | cut -d: -f1 -s) +PID=$(echo -n $_PID) # remove newlines + +echo "Generate JIT-ed DSOs using perf inject" +DEBUGINFOD_URLS='' perf inject -i "${PERF_DATA}" -j -o "${PERF_DATA}.jit" + +echo "Add JIT-ed DSOs to the build-ID cache" +for F in /tmp/jitted-${PID}-*.so; do + perf buildid-cache -a "${F}" +done + +echo "Check the symbol containing the function/module name" +NUM=$(perf report -i "${PERF_DATA}.jit" -s sym | grep -cE 'py::(foo|bar|baz):<stdin>') + +echo "Found ${NUM} matching lines" + +echo "Remove JIT-ed DSOs from the build-ID cache" +for F in /tmp/jitted-${PID}-*.so; do + perf buildid-cache -r "${F}" +done + +cleanup + +if [ "${NUM}" -eq 0 ]; then + exit 1 +fi |
