Skip to content

Instantly share code, notes, and snippets.

@bcap
Last active May 22, 2023 23:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bcap/4e0e9b3198d889ce19d0c026ec8ada12 to your computer and use it in GitHub Desktop.
Save bcap/4e0e9b3198d889ce19d0c026ec8ada12 to your computer and use it in GitHub Desktop.
small script to capture profiling data from a go process. The process needs to have the pprof web handler installed (https://pkg.go.dev/net/http/pprof)
#!/bin/bash
FLAMEGRAPH_PATH="${FLAMEGRAPH_PATH:-$HOME/code/github.com/brendangregg/FlameGraph/}"
SECONDS=10
GEN_PROFILE=true
GEN_GOROUTINE=false
GEN_BLOCK=false
GEN_MUTEX=false
GEN_ALLOC=false
GEN_HEAP=false
GEN_THREAD_CREATE=false
MKDIR=false
usage() {
cat <<EOF
$(basename $0) [-h] <source>
Positionals:
<source> The source to fetch the debugging data from. Example:
http://ip-172-16-54-3.ec2.internal/debug/pprof
Options:
-s --seconds For how long to capture data. Default: $SECONDS
-g --goroutine Also profile goroutines
-b --block Also profile blocking calls on sync primitives
-m --mutex Also profile mutexes
-a --alloc Also profile memory allocations
-e --heap Also profile heap live objects
-t --thread-create Also profile thread creations
-P --no-profile Do not generate profile. Useful if only capturing others like goroutines or mutexes
-d --mkdir Instead of dumping result files into current dir, create a more organized directory structure and store results there
-h --help Print this help.
Env Vars:
FLAMEGRAPH_PATH Path where the flamegraph repo is cloned (https://github.com/brendangregg/FlameGraph).
Default: $FLAMEGRAPH_PATH
EOF
}
while [[ $# > 0 ]]; do
case "$1" in
-s|--seconds) SECONDS=$2; shift ;;
-g|--goroutine) GEN_GOROUTINE=true ;;
-b|--block) GEN_BLOCK=true ;;
-m|--mutex) GEN_MUTEX=true ;;
-a|--alloc) GEN_ALLOC=true ;;
-e|--heap) GEN_HEAP=true ;;
-t|--thread-create) GEN_THREAD_CREATE=true ;;
-P|--no-profile) GEN_PROFILE=false ;;
-d|--mkdir) MKDIR=true ;;
-h|--help) usage; exit 0 ;;
-*) usage; exit 1 ;;
*) SOURCE=$1 ;;
esac
shift
done
[[ -z $SOURCE ]] && usage && exit 1
function log() {
echo "$@" >&2
}
TS="$(date +%Y-%m-%d-%H-%M-%S)"
if [ "$MKDIR" == "true" ]; then
SOURCE_ID=$(echo $SOURCE | sed -e 's/http:\/\///' -e 's/https:\/\///' | cut -d '/' -f 1)
DIR="$SOURCE_ID/$TS/"
mkdir -p $DIR
else
DIR=""
fi
PROFILE="${DIR}profile.$TS.${SECONDS}s.pb.gz"
PROFILE_FLAMEGRAPH="${DIR}profile.$TS.${SECONDS}s.flamegraph.svg"
GOROUTINE="${DIR}goroutine.$TS.${SECONDS}s.pb.gz"
GOROUTINE_DUMP1="${DIR}goroutine.$TS.stack-dump-level1.txt"
GOROUTINE_DUMP2="${DIR}goroutine.$TS.stack-dump-level2.txt"
BLOCK="${DIR}block-sync.$TS.${SECONDS}s.pb.gz"
MUTEX="${DIR}mutex-contentions.$TS.${SECONDS}s.pb.gz"
ALLOC="${DIR}allocations.$TS.${SECONDS}s.pb.gz"
HEAP="${DIR}heap-live.$TS.${SECONDS}s.pb.gz"
THREAD_CREATE="${DIR}thread-create.$TS.${SECONDS}s.pb.gz"
function gen_profile() {
go tool pprof -proto -output=$PROFILE "$SOURCE/profile?seconds=$SECONDS"
go tool pprof -raw $PROFILE |
$FLAMEGRAPH_PATH/stackcollapse-go.pl |
$FLAMEGRAPH_PATH/flamegraph.pl > $PROFILE_FLAMEGRAPH
}
function gen_goroutine() {
go tool pprof -proto -output=$GOROUTINE "$SOURCE/goroutine?seconds=$SECONDS" &
curl -s "$SOURCE/goroutine?debug=1" > $GOROUTINE_DUMP1 &
curl -s "$SOURCE/goroutine?debug=2" > $GOROUTINE_DUMP2 &
wait
}
function gen_block() {
go tool pprof -proto -output=$BLOCK "$SOURCE/block?seconds=$SECONDS"
}
function gen_mutex() {
go tool pprof -proto -output=$MUTEX "$SOURCE/mutex?seconds=$SECONDS"
}
function gen_alloc() {
go tool pprof -proto -output=$ALLOC "$SOURCE/allocs?seconds=$SECONDS"
}
function gen_heap() {
go tool pprof -proto -output=$HEAP "$SOURCE/heap?seconds=$SECONDS"
}
function gen_thread_create() {
go tool pprof -proto -output=$THREAD_CREATE "$SOURCE/threadcreate?seconds=$SECONDS"
}
if [ "$GEN_PROFILE" == "true" ]; then
gen_profile &
fi
if [ "$GEN_GOROUTINE" == "true" ]; then
gen_goroutine &
fi
if [ "$GEN_BLOCK" == "true" ]; then
gen_block &
fi
if [ "$GEN_MUTEX" == "true" ]; then
gen_mutex &
fi
if [ "$GEN_ALLOC" == "true" ]; then
gen_alloc &
fi
if [ "$GEN_HEAP" == "true" ]; then
gen_heap &
fi
if [ "$GEN_THREAD_CREATE" == "true" ]; then
gen_thread_create &
fi
wait
log
log "-------"
log "RESULTS"
if [ "$GEN_PROFILE" == "true" ]; then
log
log "PROFILE"
log "generated profile file at $PROFILE and profile flamegraph file at $PROFILE_FLAMEGRAPH"
log "execute the following command to open an interactive visualization of the profile file:"
log " go tool pprof -http 0.0.0.0: $PROFILE"
echo $PROFILE
echo $PROFILE_FLAMEGRAPH
fi
if [ "$GEN_GOROUTINE" == "true" ]; then
log
log "GOROUTINE"
log "generated goroutine file at $GOROUTINE as well text dumps of current state at $GOROUTINE_DUMP1 and $GOROUTINE_DUMP2"
log "execute the following command to open an interactive visualization of the goroutine file:"
log " go tool pprof -http 0.0.0.0: $GOROUTINE"
echo $GOROUTINE
echo $GOROUTINE_DUMP1
echo $GOROUTINE_DUMP2
fi
if [ "$GEN_BLOCK" == "true" ]; then
log
log "BLOCK"
log "generated blocking on synchronizations file at $BLOCK"
log "execute the following command to open an interactive visualization of the blcking on synchronizations file:"
log " go tool pprof -http 0.0.0.0: $BLOCK"
echo $BLOCK
fi
if [ "$GEN_MUTEX" == "true" ]; then
log
log "MUTEX"
log "generated mutex contentions file at $MUTEX"
log "execute the following command to open an interactive visualization of the mutex contentions file:"
log " go tool pprof -http 0.0.0.0: $MUTEX"
echo $MUTEX
fi
if [ "$GEN_ALLOC" == "true" ]; then
log
log "ALLOC"
log "generated memory allocations file at $ALLOC"
log "execute the following command to open an interactive visualization of the memory allocations file:"
log " go tool pprof -http 0.0.0.0: $ALLOC"
echo $ALLOC
fi
if [ "$GEN_HEAP" == "true" ]; then
log
log "HEAP"
log "generated heap live objects file at $HEAP"
log "execute the following command to open an interactive visualization of the heap live objects file:"
log " go tool pprof -http 0.0.0.0: $HEAP"
echo $HEAP
fi
if [ "$GEN_THREAD_CREATE" == "true" ]; then
log
log "THREAD_CREATE"
log "generated thread creations file at $THREAD_CREATE"
log "execute the following command to open an interactive visualization of the thread creations file:"
log " go tool pprof -http 0.0.0.0: $THREAD_CREATE"
echo $THREAD_CREATE
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment