user-documentation
user-documentation copied to clipboard
Document performance / profiling
Separate instructions for Linux and OSX would be especially useful, as well as instructions on how to use perf to produce something useful, and similar on OSX using other tools (dtrace etc.).
An approach for mac is to use the scripts from https://github.com/jvm-profiling-tools/perf-map-agent without using the agent, e.g.:
$ ps aux | grep hhvm # find PID
$ ./dtrace-java-record-stack $PID
$ ./dtrace-perf-map.pl /tmp/perf-$PID.map < /tmp/dtrace-$PID.data > stack_with_pid_map
Heads up - and thanks - to @jrudolph - another JIT looking at profiling on MacOS (though we have built-in support for generating perf PID maps)
For testing CLI scripts with hot jit, the CLI server is useful, e.g.:
hhvm --no-config -v Eval.JitPGO=false -v Eval.JitProfileInterpRequests=0 -m server -p 0 -v Eval.UnixServerPath=/tmp/hhvm.sock
and...
hhvm -v Eval.UseRemoteUnixServer=true -v Eval.UnixServerPath=/tmp/hhvm.sock ~/code/hhast/bin/hhast-lint.hack src/core/SuperFile.php </dev/null >/dev/null
The first run will be slow, the second run will be fast; this is useful if the jitted workload of a quick script run is representative to a long-running process.
It's arguably useful for short scripts too - while it won't be representative, it gives you a profile that isn't dominate by JIT overhead.
Lots more discussion about this in channel. Wanted to document how I've been doing this on my laptop for OSX this week, adding steps for creating png visualizations with graphviz.
Clone helper tools
git clone https://github.com/brendangregg/FlameGraph
git clone https://github.com/jvm-profiling-tools/perf-map-agent.git
export FLAMEGRAPH_DIR=$(realpath './FlameGraph')
export PERF_DIR=$(realpath './perf-map-agent')
brew install graphviz
Also download https://gist.github.com/fredemmott/dee653d84a07f6ab54c1df0e96b84b6a and name it perf.hack or something.
terminal session 1, start cli server
hhvm --no-config -v Eval.JitPGO=false -v Eval.JitProfileInterpRequests=0 -m server -p 0 -v Eval.UnixServerPath=/tmp/hhvm.sock
terminal session 2
grab the pid of that server
ps aux | grep hhvm # find pid
ls /tmp/perf-*
# there will be multiple pids, make sure the one you grab has a /tmp/perf-$PID.map file
# set it to a local variable for use later
PID=23150
now do the thing we want to profile
command='hhvm -v Eval.UseRemoteUnixServer=true -v Eval.UnixServerPath=/tmp/hhvm.sock ../hhast/bin/hhast-lint.hack path/to/some/file.php'
# run the command to warm the jit
time $command </dev/null >/dev/null
terminal session 3, profiler
# start profiler
sudo dtrace -x ustackframes=100 -n "profile-99/pid == $PID && arg1/ { @[ustack()] = count(); } tick-15s { exit(0); }" -p $PID > scratch/dtrace-$PID.data
terminal session 2, run the command to profile
This should be done just about immediately after starting dtrace. This is the part that feels most awkward and fragile. I haven't been able to get it to work using the -c "$command" option of dtrace though.
time $command </dev/null >/dev/null
terminal session 3, process results
Profiling is done, let's format the results.
# create stacks
$PERF_DIR/bin/dtrace-perf-map.pl /tmp/perf-$PID.map < dtrace-$PID.data > stack-with-pid-map-$PID
# format as single lines
$FLAMEGRAPH_DIR/stackcollapse.pl stack-with-pid-map-$PID > stack.lines
# convert to dotviz format
hhvm perf.hack > dotviz-$PID
# make a png
dot -O -Tpng dotviz-$PID
# open it in the previewer
open dotviz-$PID.png
Update: figured out a way to run the profiling step with -c:
- Start the CLI server as root with
sudo - Profile and execute command with
sudo dtrace -x ustackframes=100 -n "profile-10ms /arg1/ { @[ustack()] = count(); }" -c "hhvm -d hhvm.jit=false -v Eval.UseRemoteUnixServer=true -v Eval.UnixServerPath=$SOCKET_PATH test.php" > dtrace-$PID.data