-
-
Save csfrancis/5d088da436c987a3d61c to your computer and use it in GitHub Desktop.
Trace MRI method cache hit rate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# Uses ftrace user probes to collect and display method cache statistics from a given | |
# MRI binary. The script sleeps for a specified amount of time to collect data from | |
# any MRI process that is running on the system. | |
# | |
# Usage: trace_rb_method_cache.sh <ruby_binary> <sleep_time> | |
# | |
# Caveats: Linux only, must be run as root, requires ftrace, only tested on Ruby 2.1. | |
# | |
TRACE_DIR=/sys/kernel/debug/tracing | |
[[ $(id -u) != "0" ]] && echo "this script must be run as root" && exit 1 | |
[[ -z $1 || -z $2 || ! -f $1 ]] && echo "usage: $0 <ruby_binary> <sleep_time>" && exit 1 | |
[[ ! -d $TRACE_DIR ]] && echo "$TRACE_DIR does not exist - do you have ftrace enabled?" && exit 1 | |
RUBY_BIN=$1 | |
SLEEP_TIME=$2 | |
# attempt to find the hit and miss addresses | |
readarray MISS_HIT_ADDR < <(\ | |
gdb --batch -ex 'disas rb_method_entry' $RUBY_BIN | \ | |
awk '/rb_method_entry_get_without_cache/ && $3 == "jmpq" { miss_addr=$1 } /retq/ { hit_addr=$1 } END { if (hit_addr && miss_addr) printf "%s\n%s\n", miss_addr, hit_addr }' \ | |
) | |
[ -z $MISS_HIT_ADDR] && echo "unable to determine cache hit/miss addresses from $RUBY_BIN" && exit 1 | |
cd /sys/kernel/debug/tracing | |
# clear current tracer | |
echo 0 > tracing_on | |
echo > uprobe_events | |
# set up | |
echo nop > current_tracer | |
echo "p:rb_method_entry_miss $RUBY_BIN:${MISS_HIT_ADDR[0]}" >> uprobe_events | |
echo "p:rb_method_entry_hit $RUBY_BIN:${MISS_HIT_ADDR[1]}" >> uprobe_events | |
echo 1 > events/uprobes/enable | |
echo 1 > tracing_on | |
sleep $SLEEP_TIME | |
# report | |
echo 0 > tracing_on | |
echo 0 > events/uprobes/enable | |
cat uprobe_profile | awk '/miss/ { miss=$3; printf "%-10s %8d\n", "misses:", $3 } /hit/ { hit=$3; printf "%-10s %8d\n", "hits:", $3 } END { if (hit + miss > 0) printf "%-10s %7.2f%%\n", "hit rate:", (hit / (hit + miss)) * 100 }' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There's a bug in this script. If
write(2)
fails to write to theftrace
VFSbash
'secho
won't fail, you should use/bin/echo
instead. docs You should also useset -e
, so it'll bail in that case.