[m-dev.] logging proposal

Ian MacLarty maclarty at cs.mu.OZ.AU
Tue Feb 28 02:37:15 AEDT 2006

On Tue, Feb 28, 2006 at 01:06:16AM +1100, Mark Brown wrote:
> Hi,
> I've recently been thinking of a similar mechanism to support domain
> specific debugging.  The concept I came up with is much the same as your
> proposal, but the rationale is a bit different.
> I need to use such a feature in the tight inner loop of an execution
> engine which I wish to trace.  I would like to be able to call an I/O
> closure when the appropriate option is given at compile time, but if it
> isn't then it is crucial that the compiler optimize the call away.
> My current solution is to define a function as follows:
> 	:- func trace_engine = (bool::out(bound(no))).
> 	trace_engine = no.
> and use the function at appropriate points as follows:
> 	( trace_engine = yes ->
> 		impure do_trace_event(...)
> 	;
> 		true
> 	).
> Providing the inst `bound(no)' gives the compiler the information it
> needs to optimize the if-then-else away.  To turn this tracing code on,
> I have to change each `no' to `yes' and recompile.
> This solution is not satisfactory.  The code is intended to be distributed
> as a library -- possibly in binary form -- and asking people to edit the
> code (or even putting it through a preprocessor) is not feasible.
> What I'd like to be able to do is have the code included in debug grades,
> but completely optimized away otherwise.  Binary versions of the library
> are likely to be distributed in both debugging and non-debugging grades
> anyway, and people who use the library in their application will be able
> to provide the debugging facility to _their_ users by offering multiple
> grades.
> On 27-Feb-2006, Ian MacLarty <maclarty at cs.mu.OZ.AU> wrote:
> > As a result of the recent discussion about how to trick Mercury into not
> > optimising away logging calls, I am proposing the following simple
> > solution:
> > 
> > We add a special procedure `log' to the builtin module.  The new
> > procedure takes a string as input (or possibly an I/O closure).
> Definitely make it an I/O closure.  And the procedure has many more uses
> than just logging (you could just about implement all of mdb in Mercury
> with a feature like this!), so call it something more generic like
> `debugging_event'.  (Admittedly, my do_trace_event currently just logs some
> information on stdout, but I would like to expand it to be a fully
> interactive, mdb-style debugger.)

Yes I agree.  As long as you had logging in the right places in you
library you could make a domain specific debugger.

> > The
> > compiler is then modified to treat calls to log as being the same as
> > true, unless an "--enable-logging" options is given.  If this option is
> > given then the logging predicates write their output somewhere
> I'd suggest using the mdb technique of both a compile-time and a run-time
> option.  The run-time option would be via the MERCURY_OPTIONS environment
> variable -- if the procedure is activated with the compile-time option,
> then the first thing it does is check a global flag in the runtime system
> to see if the run-time option was given.  This way you can easily turn off
> the events without recompiling, and without too much overhead.

I agree.

> And I think the right compile-time option is `--debug' and its equivalents,
> but more on that below.
> > (where they write their output could be given by another mmc option).
> There could be lots of different kinds of information you may want to
> communicate to this subsystem, and we won't be able to anticipate all of
> it.  You also might prefer to specify the output location at run-time
> rather than compile time.  Hence I think it would be better to communicate
> via environment variables.
> Furthermore, an application may link to two different libraries that use
> this feature and you might therefore want to send the logs to separate
> places, but you couldn't do that with either a compile-time or a run-time
> option.

So are you saying if you make the argument an I/O closure then you can
implement your debugger to behave however you want?  If so then I agree
with you.

> > 
> > What are the feelings on introducing such a scheme?
> Nasty, dirty and kludgy as it is, I think it's absolutely necessary.
> > Clearly some kind
> > of logging feature is necessary, especially for very long running
> > programs that would be too slow in debugging grades.
> I'm not so sure I agree with this line of reasoning.  If your debugging
> events are going to be fairly frequently doing I/O, then surely the cost
> of the I/O is going to outweigh the cost of debugging anyway (particularly
> with --trace-optimized).
> If it is only rarely called, or only rarely doing output, then I don't
> see this feature as being necessary -- using impure code and testing the
> current value of a mutable to decide whether to have the event or not
> would seem to be an acceptable solution.
> Because of this, and because of the situation I outlined at the start,
> I think it would be best to tie the feature to the debugging grades.
> This would also effectively stop people from trying to use the feature
> in production code, which they really shouldn't do.

I see your point and I think I agree (though I'll need to sleep on it

> > Also it would be
> > better that user's could add a logging mechanism to their code without
> > tricking and/or lying to the compiler.
> Oho, I'm afraid this technique is still very much stretching the truth.

Your right :-)
We should aim to seperate out the code that defines the behaviour
of the application, and the code that is for observing/debugging the
execution of the program.  This proposal doesn't quite get there.

Perhaps a better solution would be to have a `log' (or `debug')
"goal", so in your code you might have a something like:

debug io.format("X = %i\n", [i(X)])

This makes the distinction much clearer.

> You can backtrack over this tracing code, remember, but the side effects
> are obviously not undone and the compiler is in no way informed of this
> fact.  This is definitely still an experts only feature, IMHO.

I would think this behaviour would be designed, since the logging would
be for observing exactly what your program is doing.

> > 
> > We could also have different levels of logging.
> That's another thing that could be communicated via environment variables.

Of course.  I think controlling things via env vars is a good idea.

mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au

More information about the developers mailing list