# Copyright (C) 2001-2011, Parrot Foundation.

=head1 NAME

docs/dev/profiling.pod - Profiling Parrot

=head1 DESCRIPTION

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

=head2 Summary

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 C<tools/dev/pprof2cg.pl>, which
is installed under C<lib/3.6.0-devel/tools/dev/pprof2cg.pl> in a standard
installation.  

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

=head2 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 C<perl6>, you'll need to run C<perl6.pbc> directly instead.
For example, if you run C<./perl6 foo.p6>, instead run C<parrot perl6.pbc foo.p6>.
If your code can run normally when passed to the C<parrot> executable
directly, you can easily profile it.

To profile, add C<-Rprofiling> to the command-line invocation of C<parrot>
before any C<.pbc> files are added, e.g. C<./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 F<tools/dev/pprof2cg.pl> to generate Callgrind-compatible output from this file.

You now have a raw profile of your code.

=head2 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.
F<tools/dev/pprof2cg.pl> 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. F<kcachegrind>) can understand.

=head2 Bugs and Surprises

In theory the output of F<pprof2cg.pl> should be compatible with F<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.

=head2 Environment Variables

=head3 Generally Useful Variables

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

=over 4

=item C<PARROT_PROFILING_FILENAME>

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 F<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 C<stdout> and C<stderr>.  When
either of these values are detected (case-insensitively), Parrot will print its
profiling output to STDOUT or STDERR.

=item C<PARROT_PROFILING_ANNOTATIONS>

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.

=item C<PARROT_PROFILING_OUTPUT>

This determines the type of output which will contain the profile.  Current
options are C<pprof> and C<none>.  C<pprof> is the default and is a ascii-based
human-readable format.  It can be post-processed into a Callgrind-compatible
format by C<tools/dev/pprof2cg.pl>.  C<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.

=back

=head3 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.

=over 4

=item C<PARROT_PROFILING_CANONICAL_OUTPUT>

When this is set, the profiling runcore will record all addresses as a single
constant value and all times as C<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
C<--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.

=back

=cut
