hpc-strobe: Hpc-generated strobes for a running Haskell program

[ bsd3, debug, library, trace ] [ Propose Tags ] [ Report a vulnerability ]

A rudimentary library that demonstrates the possibility of using Hpc (Haskell Program Coverage) to inspect the state of a running Haskell program. Use of the library involves a simple change of the main function and also requires the program to be enabled for hpc. At the time of writing, this means using a fairly recent version of GHC and compiling the Haskell code with the -fhpc option.


[Skip to Readme]

Modules

[Index]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.1
Dependencies base, filepath, hpc [details]
License BSD-3-Clause
Author Thorkil Naur
Maintainer naur@post11.tele.dk
Category Trace, Debug
Uploaded by ThorkilNaur at 2009-05-08T18:49:44Z
Distributions NixOS:0.1
Reverse Dependencies 1 direct, 0 indirect [details]
Downloads 1350 total (3 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs uploaded by user
Build status unknown [no reports yet]

Readme for hpc-strobe-0.1

[back to package description]
=======================================================================
README: hpc-strobe: Hpc-generated strobes for a running Haskell program
=======================================================================

hpc-strobe is a rudimentary library that demonstrates the possibility of
using Hpc (Haskell Program Coverage) to inspect the state of a running
Haskell program. Please refer to

  Andy Gill and Colin Runciman: "Haskell Program Coverage", in
  Haskell Workshop, ACM Press, 2007

for a description of Hpc. At the time of writing this (2009-May-08),
the paper is available at

  http://www.ittc.ku.edu/~andygill/papers/Hpc07.pdf

In ordinary use of Hpc, a single so-called tix file is produced at the
end of a run. The tix file records how many times each expression has
been used during the run. This can be used to mark up the source code,
identifying expressions that have not been used.

hpc-strobe uses the basic machinery provided by Hpc to produce multiple
tix files, also called strobes, representing the coverage at different
times while the program is running. By subtracting such two tix files,
again using Hpc machinery, a tix file representing the expressions used
between the times of recording the subtracted tix files is produced.
This may be used, for example, to get a better idea of what a
long-running program is doing. It could also be used as a profiling
tool, getting information about how many times individual expressions
are used.

A program is included whose strobe differences produce a crude rendering
of an analog clock when they are used to mark up the source code using
Hpc.

Use of the library involves a simple change of the main function and
also requires the program to be enabled for hpc. At the time of writing,
this means using a fairly recent version of GHC and compiling the
Haskell code with the -fhpc option.

In the rest of this README, please find (1) download information; (2)
build and install information; (3) information on how to run the
demonstration program and render the analog clock; (4) a bit of
background information; and (5) some final remarks. Information on how
to use the library can be found in the haddock documentation which is
based on comments in src/Trace/Hpc/Strobe.hs in the package.

1. Downloading hpc-strobe
-------------------------

hpc-strobe is on hackage, so for example:

  $ wget http://hackage.haskell.org/packages/archive/hpc-strobe/0.1/hpc-strobe-0.1.tar.gz

2. Building and installing hpc-strobe
-------------------------------------

First unpack the package:

  $ tar xvz hpc-strobe-0.1.tar.gz

Then build and install the Cabal way:

  $ cd hpc-strobe-0.1
  $ runhaskell Setup.hs configure # Additional options may be used
  $ runhaskell Setup.hs build
  $ runhaskell Setup.hs haddock # Optional
  $ runhaskell Setup.hs install # Privileges (sudo) may be needed

For example:

  $ tar xvfz ../../test/hpc/hpc-strobeDarcsRepository/hpc-strobe/dist/hpc-strobe-0.1.tar.gz 
  hpc-strobe-0.1/
  hpc-strobe-0.1/demonstration/
  hpc-strobe-0.1/demonstration/showClock1.sh
  hpc-strobe-0.1/demonstration/StrobeClock.hs
  hpc-strobe-0.1/demonstration/strobeHpcDiff1.sh
  hpc-strobe-0.1/hpc-strobe.cabal
  hpc-strobe-0.1/LICENSE
  hpc-strobe-0.1/README
  hpc-strobe-0.1/Setup.hs
  hpc-strobe-0.1/src/
  hpc-strobe-0.1/src/Trace/
  hpc-strobe-0.1/src/Trace/Hpc/
  hpc-strobe-0.1/src/Trace/Hpc/Strobe.hs
  $ cd hpc-strobe-0.1/
  $ runhaskell Setup.hs configure --user --prefix=/Users/thorkilnaur/tn/install/hpc-strobe-0.1
  Configuring hpc-strobe-0.1...
  $ runhaskell Setup.hs build
  Preprocessing library hpc-strobe-0.1...
  Building hpc-strobe-0.1...
  [1 of 1] Compiling Trace.Hpc.Strobe ( src/Trace/Hpc/Strobe.hs, dist/build/Trace/Hpc/Strobe.o )
  ar: creating archive dist/build/libHShpc-strobe-0.1.a
  $ runhaskell Setup.hs haddock
  Preprocessing library hpc-strobe-0.1...
  Running Haddock for hpc-strobe-0.1...
  Documentation created: dist/doc/html/hpc-strobe/index.html
  $ runhaskell Setup.hs install
  Installing: /Users/thorkilnaur/tn/install/hpc-strobe-0.1/lib/hpc-strobe-0.1/ghc-6.8.2
  Registering hpc-strobe-0.1...
  Reading package info from "dist/installed-pkg-config" ... done.
  Saving old package config file... done.
  Writing new package config file... done.
  $ 

3. Running the demonstration program
------------------------------------

I show how to run he demonstration program in-place in the unpacked
package directory:

  $ cd demonstration
  $ ghc --version
  The Glorious Glasgow Haskell Compilation System, version 6.8.2
  $ ghc --make StrobeClock.hs -fhpc
  [1 of 1] Compiling Main             ( StrobeClock.hs, StrobeClock.o )
  Linking StrobeClock ...
  $ mkdir tixfiles
  $ ./StrobeClock tixfiles 
  StrobeClock(2009-May-08 10.41): Canvas pixel height 39, pixel width 39
  StrobeClock(2009-May-08 10.41): 634
  StrobeClock(2009-May-08 10.41): 1266
  ...

StrobeClock never stops, so at this point, enter a separate shell and

  $ cd hpc-strobe-0.1/demonstration 
  $ ls -tr tixfiles | tail -n 3
  StrobeClock_254.tix
  StrobeClock_255.tix
  StrobeClock_256.tix
  $ 

to watch the growing list of strobes.

Note: StrobeClock will not complain if you forget to create the tixfiles
directory: In that case, no tixfiles will be written. Whether this
should be considered an error or a feature, I haven't decided.

To produce a single strobe difference, a shell script strobeHpcDiff1.sh
is provided. For example:

  $ sh strobeHpcDiff1.sh . tixfiles StrobeClock 0 5
  Writing: Main.hs.html
  Writing: hpc_index.html
  Writing: hpc_index_fun.html
  Writing: hpc_index_alt.html
  Writing: hpc_index_exp.html
  strobeHpc_StrobeClock_5_SUB_0_20090508_140251/
  strobeHpc_StrobeClock_5_SUB_0_20090508_140251/Main.hs.html
  $ 

This deposits marked-up source code in a time-stamped directory. It
also produces a .tar.gz file for that directory. Please look at the
strobeHpcDiff1.sh code itself for usage information.

Now point your browser to the Main.hs.html file in the time-stamped
directory. On my Mac OS X, I can do

  $ /Applications/Firefox.app/Contents/MacOS/firefox strobeHpc_StrobeClock_5_SUB_0_20090508_140251/Main.hs.html &
  [1] 23707
  $ 

but something different may be needed. Now scroll down a few lines in
this marked-up version of the StrobeClock.hs code to display the canvas
function. You should be able to make out a crude rendering of an analog
clock, showing the local time of day. And since we have taken the
difference over 5 strobes, with 1 second between each, the seconds hand
on the clock is smeared, covering those 5 seconds.

For a more dynamic experience, with StrobeClock still running:

  $ sh showClock1.sh 
  showClock1.sh: Skip over tixfiles/StrobeClock_0.tix to tixfiles/StrobeClock_1.tix
  showClock1.sh: Skip over tixfiles/StrobeClock_1.tix to tixfiles/StrobeClock_2.tix
  ...
  showClock1.sh: Skip over tixfiles/StrobeClock_30.tix to tixfiles/StrobeClock_31.tix
  showClock1.sh: Mark up tixfiles/StrobeClock_31.tix to tixfiles/StrobeClock_32.tix
  Writing: Main.hs.html
  Writing: hpc_index.html
  Writing: hpc_index_fun.html
  Writing: hpc_index_alt.html
  Writing: hpc_index_exp.html
  ...

This creates a directory, ClockDisplay, and maintains in this directory
a marked-up Main.hs.html that corresponds to the difference between the
third- and second-latest strobes in the tixfiles directory.
(showClock1.sh assumes that the tixfiles directory is named "tixfiles"
and also that the tixfile filename prefix is "StrobeClock".)

Then point your browser to this file, for example (again after entering
a new shell: showClock1.sh runs forever; also, I need to close the
other firefox before starting a new one):

  $ cd hpc-strobe-0.1/demonstration 
  $ /Applications/Firefox.app/Contents/MacOS/firefox ClockDisplay/Main.hs.html &
  [1] 24813
  $ 

This will show the most recently marked-up strobe difference, hence the
current local time will be rendered in the canvas function. Smearing
may occur, but refreshing the display usually helps.

In addition to PPC Mac OS X 10.4 with GHC 6.8.2, the demonstration has
been tried successfully on Windows with GHC 6.8.2 with both MSYS and
Cygwin; and on Ubuntu x86 Linux with GHC 6.10.2.

4. Background
-------------

The path to using the reflect interface in Hpc started with my desire to
investigate a long-winding darcs pull (some GHC HEAD into GHC STABLE).
See http://bugs.darcs.net/issue1075.  Earlier, to investigate the
HughesPJ pretty-printing library, I had written a simple tracer that did
a source-to-source transformation of Haskell code, inserting calls to
Debug.Trace.trace for all top-level definitions in a Haskell module. See
http://hackage.haskell.org/trac/ghc/ticket/1337. This was at a point in
time where Hpc was not working. So my initial idea was to do something
similar to darcs, transforming selected darcs modules to figure out what
they were doing.

The work started around 2008-Sep-02. After struggling for a while, I
had settled on a modified version of the Hpc.c that comes with the GHC
runtime system that wrote out tix files regularly. Immediately
afterwards, however, I stumbled over the Trace.Hpc.Reflect and
Trace.Hpc.Tix modules that supported exactly what I needed. Thanks to
the foresight of Andy Gill and Colin Runciman, everything turned out to
be surprisingly simple. In fact, a major motivation for publishing the
present library is simply to make this technique better known. The
hpc-strobe library itself is really not adding anything significant to
Hpc itself.

At the Hac5/darcs sprint 2, I gave a brief presentation of the
technique:

  http://blog.darcs.net/2009/04/darcs-hacking-sprint-2-report.html

Thanks to Don Steward for helping here.

5. Final words
--------------

As mentioned, the contents of the hpc-strobe library itself is really
not particularly significant and it is easy to imagine a number of
generalizations and variations of the technique that opens up what I
believe is a fairly rich field of valuable applications.

I should mention the hpc-tracer library by Andy Gill and Colin Runciman:

  http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hpc-tracer

I must admit that I have not studied this library in detail, but it
clearly seems to be headed in much the same direction as hpc-strobe,
but with a more elaborate user interface.

Thorkil Naur