需要,分两类:
libjvm.so 等 native 符号:来自 ELF 符号表。
- JIT 编译的 Java 方法:依赖
/tmp/perf-<java-pid>.map。
脚本中的:
会在 JVM 退出时生成 JIT 地址到 Java 方法名的映射。-XX:+PreserveFramePointer 用于保证调用栈,-XX:+DebugNonSafepoints 提高非 safepoint 位置的可见性。
我已经更新 profile-par.sh,现在输出目录会同时保存:
perf.data
perf-<pid>.map
java.pid
top.txt
stacks.folded
flame.svg
如果之后单独重新解析 perf.data,需要先恢复 map:
cp profile-par-c3-*/perf-*.map /tmp/
perf report -i profile-par-c3-*/perf.data
否则 JIT 代码通常只会显示为地址或 [JIT],看不到具体 Java 方法名。
#!/usr/bin/env bash
set -euo pipefail
mode=${1:?usage: $0 c2|c3}
[[ $mode == c2 ]] && compiler=-XX:-UseJeandleCompiler || compiler=-XX:+UseJeandleCompiler
out="profile-par-$mode-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$out"
numactl -N 1 -m 1 perf record -F 99 -e cycles:u -g --call-graph fp -o "$out/perf.data" -- \
sh -c 'echo $$ >"$1"; shift; exec "$@"' sh "$out/java.pid" \
build/linux-aarch64-server-release/images/jdk/bin/java -XX:-TieredCompilation "$compiler" \
-XX:+UnlockDiagnosticVMOptions -XX:+PreserveFramePointer -XX:+DebugNonSafepoints \
-XX:+DumpPerfMapAtExit \
-jar renaissance-gpl-0.16.0.jar -r 8 par-mnemonics >"$out/run.log" 2>&1
pid=$(<"$out/java.pid")
cp "/tmp/perf-$pid.map" "$out/"
perf report -i "$out/perf.data" --stdio --no-children -g none >"$out/top.txt"
perf script -i "$out/perf.data" | target/tools/FlameGraph/stackcollapse-perf.pl >"$out/stacks.folded"
target/tools/FlameGraph/flamegraph.pl --colors java "$out/stacks.folded" >"$out/flame.svg"
echo "profile written to $out"
需要,分两类:
libjvm.so等 native 符号:来自 ELF 符号表。/tmp/perf-<java-pid>.map。脚本中的:
会在 JVM 退出时生成 JIT 地址到 Java 方法名的映射。
-XX:+PreserveFramePointer用于保证调用栈,-XX:+DebugNonSafepoints提高非 safepoint 位置的可见性。我已经更新 profile-par.sh,现在输出目录会同时保存:
如果之后单独重新解析
perf.data,需要先恢复 map:否则 JIT 代码通常只会显示为地址或
[JIT],看不到具体 Java 方法名。