docs/dev/profiling.pod - Profiling Parrot


This file documents the use of Parrot's profiling runcore.


This file provides an introduction on how to profile code written in a Parrot-hosted language. Parrot includes profiling as a built-in runcore which outputs a textual line-based format. This file will generally need to be post-processed, either by a custom script or by tools/dev/, which is installed under lib/3.6.0-devel/tools/dev/ in a standard installation.

The profiling runcore can record any annotations added by HLL compilers, though annotations are ignored by and are not recorded by default. This and various other aspects of profiling can be controlled through environment variables, as described below.

Running Code Under the Profiler

In Parrot, profiling capability is provided in the form of a built-in runcore and is available with any installed version of Parrot. The only condition is that you be able to run your code as a series of arguments passed directly to the parrot executable, rather than a "fakecutable" (a native executable that runs built-in hard-coded Parrot bytecode). If you usually run your code via a fakecutable such as perl6, you'll need to run perl6.pbc directly instead. For example, if you run ./perl6 foo.p6, instead run parrot perl6.pbc foo.p6. If your code can run normally when passed to the parrot executable directly, you can easily profile it.

To profile, add -Rprofiling to the command-line invocation of parrot before any .pbc files are added, e.g. ./parrot -Rprofiling perl6.pbc foo.p6. Your program will run more slowly and will end with a message such as

  PROFILING RUNCORE: wrote profile to parrot.pprof.4251

Use tools/dev/ to generate Callgrind-compatible output from this file.

You now have a raw profile of your code.

Profile Post-processing Tools

The profiling runcore spits out a line-oriented plain-text file which contains the timing information for each executed instruction and a description of each context change. This data should be sufficient to determine any information about the timing of instructions and subs. The format is intended to be straightforward and amenable to processing by external tools. tools/dev/ is included with Parrot and attempts to read a profile generated by the profiling runcore and produce a profile which callgrind-compatible tools (e.g. kcachegrind) can understand.

Bugs and Surprises

In theory the output of should be compatible with kcachegrind. In practice, it isn't. If you have a use case that reliably produces non-sensical results, talk to cotto on #parrot or file a ticket.

Environment Variables

Generally Useful Variables

This section includes environment variables which are likely to be of interest to developers wishing to profile HLL code.

This determines the full name of the file where the output will be written, if any. Parrot does not check if the filename exists before opening it for writing and will happily truncate and overwrite any existing files, including previous profiles.If no value is specified, Parrot will write to a file named parrot.pprof.X, where X is the PID of the Parrot process. When the profiling runcore exits, it will print a message announcing where the profile was written.This variable can also have the special values stdout and stderr. When either of these values are detected (case-insensitively), Parrot will print its profiling output to STDOUT or STDERR.
This determines whether PIR annotations will be recorded as part of the profile. Annotations are necessary when profiling HLL code, but will cause the profiling runcore to run more slowly. By default, they are disabled. Set this value to enable them.
This determines the type of output which will contain the profile. Current options are pprof and none. pprof is the default and is a ascii-based human-readable format. It can be post-processed into a Callgrind-compatible format by tools/dev/ none writes nothing to the output file. It is most useful for testing and optimizing the profiling runcore itself. It is expected to be of little interest to users wishing to profile PIR and HLL code.

Debugging-Related Variables

These variables are intended primarly for testing of the profiling code itself. You can play with them if you want, but they probably won't help you get any useful work done.

When this is set, the profiling runcore will record all addresses as a single constant value and all times as 1. This option is useful primarily for testing, where it's helpful to have a way to ensure that a given chunk of code will always produce exactly the same profile. If you want this feature enabled, you also probably want to pass a fixed hash seed to Parrot via --hash-seed 1324 to avoid any non-deterministic behavior that hash seed randomization may cause.This variable is not useful apart from testing the profiling runcore and will most certainly not help you find hotspots in your code.