The nhc13 tracer
The nhc13 tracer is applicable to a wide class of Haskell
computations, including those that:
- run to completion producing output, though perhaps not the
output expected; or
- halt with a run-time error, such as a pattern-matching
failure or a black hole; or
- appear to be stuck in an a recursive loop, whether or not
output is being produced.
To obtain a trace of a computation:
-
Compile all modules of the program with the -T option;
also specify -T at link-time. Using hmake -T does
all the necessary compiling and linking automatically.
-
Run the program with a larger-than-normal heap space.
For example, give additional arguments +RTS -H10M -RTS to specify
a ten-megabyte heap.
If the program halts, any normal output from the program will
be followed by a summary line indicating that a trace is
now available. The program does not terminate but waits
to be attached to a trace-browser.
If it seems the program is stuck in an unproductive loop
force the trace-available state by keying an interrupt
(usually ctrl-C).
To explore traces using the trace browser
-
If there is not already a trace browser running, start
one by giving the shell command nhc13tracer'.
(The browser is a separate program that communicates with
a trace-producing Haskell program.)
-
With a traced Haskell program in the trace-available
state, click over the `connect' button in the upper part
of the trace-browser window.
Any program output is shown in the lower panel of the
trace browser. Clicking over a section of the output causes a
parent expression for that output to be displayed in the upper trace
panel. There is one section of output for each monadic output
operation performed by the program, and any currently selected
section is shown in blue.
If a run-time error has occurred, or the computation has been interrupted,
the initial trace panel displays the expression under
evaluation at the time.
-
Moving the mouse over expressions in the trace panel causes
the display of various forms of highlighting. The most important
ones are:
- a red box highlights any currently-selected subexpression S;
- expressions with the same source as S are shown in blue;
- if the parent redex of S is already on display it is shown
with a background highlight in yellow.
-
Beyond the normal syntax for Haskell expressions, five special
symbols may occur in trace expressions:
bottom | the undefined value, as usual;
| empty box | a placeholder for a subexpression
suppressed for
the time-being (eg. to avoid over-wide displays);
| slant box | a placeholder for an expression that
is not available because it is part of a
trusted computation not recorded in
the trace -- however, the parent redex
is available;
| cross box | a placeholder for an expression that
is not available -- nor are its ancestral
redexes, as they have been
pruned from the trace.
| within | shown between the values of case
subjects, conditions or guards and those of
the expressions they belong to
|
Mouse clicks in the trace panel have the following effects:
left: | show the parent redex of S, if any;
(or, if the parent is already on
display, remove it along with any of its
ancestors also on display)
| middle: | if S is a place-holder, expand it;
(or, if not, contract S to a
place-holder)
| right: | show where S originates in the
source program, displayed in lower panel.
(If S is a name, a plain right-click
requests the corresponding point of use,
but shift-right-click requests the
definition.)
|
Partial traces (avoiding detail and saving space)
There are two ways to specify a partial trace:
-
Trusting: details of computation within specified modules or
functions are omitted from the trace. The choice of which
components to trust and which to suspect can be made at
compile-time but can also be altered at run-time.
At compile-time, use -T -trusted to compile a trusted module.
At run-time, after +RTS alter the compile-time specification
of trusted modules or functions by -dt name, or suspected
ones by -ds name. Name functions in full with the
module name as prefix: for example, -ds BinaryTree.Delete.
The flags -dtr and -dsr can be used to trust or suspect
not only the
named module but also all other modules that it (recursively)
depends on.
By default only the Prelude is trusted.
-
Pruning:at each garbage collection, trace structure more
than a specified distance k from all continuing evaluation points
is discarded. Any pruning is specified at run-time: for example,
+RTS -k2 -RTS.
By default there is no pruning.
Four limiting factors
-
The tracer does not currently handle programs involving
I/O other than to standard input and/or standard output.
-
List comprehensions are traced in terms of their explicit
translations to higher-order function applications.
-
Traced execution can take 10-30 times longer than normal.
-
Traced execution without pruning requires heap memory in
rough proportion to the length of the computation.
(As a rough rule of thumb, 100 bytes of heap memory are
required for each traced reduction.)
We plan to address all four of these limitations in future versions.
The latest updates to these pages are available on the WWW from
http://www.cs.york.ac.uk/fp/nhc13/
1998.06.18
York Functional Programming Group
Colin.Runciman@cs.york.ac.uk
|