Usage:
hp2ps [flags] [<file>[.hp]]
The program
    hp2ps converts a heap profile as produced
    by the -h<break-down> runtime option into a
    PostScript graph of the heap profile. By convention, the file to
    be processed by hp2ps has a
    .hp extension. The PostScript output is
    written to <file>@.ps. If
    <file> is omitted entirely, then the
    program behaves as a filter.
hp2ps is distributed in
    ghc/utils/hp2ps in a GHC source
    distribution. It was originally developed by Dave Wakeling as part
    of the HBC/LML heap profiler.
The flags are:
-dIn order to make graphs more readable,
          hp2ps sorts the shaded bands for each
          identifier. The default sort ordering is for the bands with
          the largest area to be stacked on top of the smaller ones.
          The -d option causes rougher bands (those
          representing series of values with the largest standard
          deviations) to be stacked on top of smoother ones.
-bNormally, hp2ps puts the title of
          the graph in a small box at the top of the page. However, if
          the JOB string is too long to fit in a small box (more than
          35 characters), then hp2ps will choose to
          use a big box instead.  The -b option
          forces hp2ps to use a big box.
-e<float>[in|mm|pt]Generate encapsulated PostScript suitable for
          inclusion in LaTeX documents.  Usually, the PostScript graph
          is drawn in landscape mode in an area 9 inches wide by 6
          inches high, and hp2ps arranges for this
          area to be approximately centred on a sheet of a4 paper.
          This format is convenient of studying the graph in detail,
          but it is unsuitable for inclusion in LaTeX documents.  The
          -e option causes the graph to be drawn in
          portrait mode, with float specifying the width in inches,
          millimetres or points (the default).  The resulting
          PostScript file conforms to the Encapsulated PostScript
          (EPS) convention, and it can be included in a LaTeX document
          using Rokicki's dvi-to-PostScript converter
          dvips.
-gCreate output suitable for the gs PostScript previewer (or similar). In this case the graph is printed in portrait mode without scaling. The output is unsuitable for a laser printer.
-lNormally a profile is limited to 20 bands with
          additional identifiers being grouped into an
          OTHER band. The -l flag
          removes this 20 band and limit, producing as many bands as
          necessary. No key is produced as it won't fit!. It is useful
          for creation time profiles with many bands.
-m<int>Normally a profile is limited to 20 bands with
          additional identifiers being grouped into an
          OTHER band. The -m flag
          specifies an alternative band limit (the maximum is
          20).
-m0 requests the band limit to be
          removed. As many bands as necessary are produced. However no
          key is produced as it won't fit! It is useful for displaying
          creation time profiles with many bands.
-pUse previous parameters. By default, the PostScript
          graph is automatically scaled both horizontally and
          vertically so that it fills the page.  However, when
          preparing a series of graphs for use in a presentation, it
          is often useful to draw a new graph using the same scale,
          shading and ordering as a previous one. The
          -p flag causes the graph to be drawn using
          the parameters determined by a previous run of
          hp2ps on file. These
          are extracted from file@.aux.
-sUse a small box for the title.
-t<float>Normally trace elements which sum to a total of less
          than 1% of the profile are removed from the
          profile. The -t option allows this
          percentage to be modified (maximum 5%).
-t0 requests no trace elements to be
          removed from the profile, ensuring that all the data will be
          displayed.
-cGenerate colour output.
-yIgnore marks.
-?Print out usage information.
(Notes kindly offered by Jan-Willem Maessen.)
The FOO.hp file produced when you ask for the
heap profile of a program FOO is a text file with a particularly
simple structure. Here's a representative example, with much of the
actual data omitted:
JOB "FOO -hC" DATE "Thu Dec 26 18:17 2002" SAMPLE_UNIT "seconds" VALUE_UNIT "bytes" BEGIN_SAMPLE 0.00 END_SAMPLE 0.00 BEGIN_SAMPLE 15.07 ... sample data ... END_SAMPLE 15.07 BEGIN_SAMPLE 30.23 ... sample data ... END_SAMPLE 30.23 ... etc. BEGIN_SAMPLE 11695.47 END_SAMPLE 11695.47
The first four lines (JOB, DATE, SAMPLE_UNIT, VALUE_UNIT) form a
header.  Each block of lines starting with BEGIN_SAMPLE and ending
with END_SAMPLE forms a single sample (you can think of this as a
vertical slice of your heap profile).  The hp2ps utility should accept
any input with a properly-formatted header followed by a series of
*complete* samples.
You can look at particular regions of your profile simply by loading a
copy of the .hp file into a text editor and deleting the unwanted
samples.  The resulting .hp file can be run through hp2ps and viewed
or printed.
The .hp file is generated incrementally as your
program runs.  In principle, running hp2ps on the incomplete file
should produce a snapshot of your program's heap usage.  However, the
last sample in the file may be incomplete, causing hp2ps to fail.  If
you are using a machine with UNIX utilities installed, it's not too
hard to work around this problem (though the resulting command line
looks rather Byzantine):
  head -`fgrep -n END_SAMPLE FOO.hp | tail -1 | cut -d : -f 1` FOO.hp \
    | hp2ps > FOO.ps
The command fgrep -n END_SAMPLE FOO.hp finds the
end of every complete sample in FOO.hp, and labels each sample with
its ending line number.  We then select the line number of the last
complete sample using tail and cut.  This is used as a
parameter to head; the result is as if we deleted the final
incomplete sample from FOO.hp.  This results in a properly-formatted
.hp file which we feed directly to hp2ps.
The gv and ghostview programs have a "watch file" option can be used to view an up-to-date heap profile of your program as it runs. Simply generate an incremental heap profile as described in the previous section. Run gv on your profile:
gv -watch -seascape FOO.ps
If you forget the -watch flag you can still select
"Watch file" from the "State" menu.  Now each time you generate a new
profile FOO.ps the view will update automatically.
This can all be encapsulated in a little script:
  #!/bin/sh
  head -`fgrep -n END_SAMPLE FOO.hp | tail -1 | cut -d : -f 1` FOO.hp \
    | hp2ps > FOO.ps
  gv -watch -seascape FOO.ps &
  while [ 1 ] ; do
    sleep 10 # We generate a new profile every 10 seconds.
    head -`fgrep -n END_SAMPLE FOO.hp | tail -1 | cut -d : -f 1` FOO.hp \
      | hp2ps > FOO.ps
  done
Occasionally gv will choke as it tries to read an incomplete copy of
FOO.ps (because hp2ps is still running as an update
occurs).  A slightly more complicated script works around this
problem, by using the fact that sending a SIGHUP to gv will cause it
to re-read its input file:
  #!/bin/sh
  head -`fgrep -n END_SAMPLE FOO.hp | tail -1 | cut -d : -f 1` FOO.hp \
    | hp2ps > FOO.ps
  gv FOO.ps &
  gvpsnum=$!
  while [ 1 ] ; do
    sleep 10
    head -`fgrep -n END_SAMPLE FOO.hp | tail -1 | cut -d : -f 1` FOO.hp \
      | hp2ps > FOO.ps
    kill -HUP $gvpsnum
  done