jitdump-python.sh 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. #!/bin/bash
  2. # python profiling with jitdump
  3. # SPDX-License-Identifier: GPL-2.0
  4. SHELLDIR=$(dirname $0)
  5. # shellcheck source=lib/setup_python.sh
  6. . "${SHELLDIR}"/lib/setup_python.sh
  7. OUTPUT=$(${PYTHON} -Xperf_jit -c 'import os, sys; print(os.getpid(), sys.is_stack_trampoline_active())' 2> /dev/null)
  8. PID=${OUTPUT% *}
  9. HAS_PERF_JIT=${OUTPUT#* }
  10. rm -f /tmp/jit-${PID}.dump 2> /dev/null
  11. if [ "${HAS_PERF_JIT}" != "True" ]; then
  12. echo "SKIP: python JIT dump is not available"
  13. exit 2
  14. fi
  15. PERF_DATA=$(mktemp /tmp/__perf_test.perf.data.XXXXXX)
  16. cleanup() {
  17. echo "Cleaning up files..."
  18. rm -f ${PERF_DATA} ${PERF_DATA}.jit /tmp/jit-${PID}.dump /tmp/jitted-${PID}-*.so 2> /dev/null
  19. trap - EXIT TERM INT
  20. }
  21. trap_cleanup() {
  22. echo "Unexpected termination"
  23. cleanup
  24. exit 1
  25. }
  26. trap trap_cleanup EXIT TERM INT
  27. echo "Run python with -Xperf_jit"
  28. cat <<EOF | perf record -k 1 -g --call-graph dwarf -o "${PERF_DATA}" \
  29. -- ${PYTHON} -Xperf_jit
  30. def foo(n):
  31. result = 0
  32. for _ in range(n):
  33. result += 1
  34. return result
  35. def bar(n):
  36. foo(n)
  37. def baz(n):
  38. bar(n)
  39. if __name__ == "__main__":
  40. baz(1000000)
  41. EOF
  42. # extract PID of the target process from the data
  43. _PID=$(perf report -i "${PERF_DATA}" -F pid -q -g none | cut -d: -f1 -s)
  44. PID=$(echo -n $_PID) # remove newlines
  45. echo "Generate JIT-ed DSOs using perf inject"
  46. DEBUGINFOD_URLS='' perf inject -i "${PERF_DATA}" -j -o "${PERF_DATA}.jit"
  47. echo "Add JIT-ed DSOs to the build-ID cache"
  48. for F in /tmp/jitted-${PID}-*.so; do
  49. perf buildid-cache -a "${F}"
  50. done
  51. echo "Check the symbol containing the function/module name"
  52. NUM=$(perf report -i "${PERF_DATA}.jit" -s sym | grep -cE 'py::(foo|bar|baz):<stdin>')
  53. echo "Found ${NUM} matching lines"
  54. echo "Remove JIT-ed DSOs from the build-ID cache"
  55. for F in /tmp/jitted-${PID}-*.so; do
  56. perf buildid-cache -r "${F}"
  57. done
  58. cleanup
  59. if [ "${NUM}" -eq 0 ]; then
  60. exit 1
  61. fi