On Sat, Jun 13, 2015 at 5:49 AM, Torsten Bergmann <asta...@gmx.de> wrote:
> Hi,
>
> for tracing and logging one could easily write:
>
> foo
>   ...
>   Log enabled ifTrue: [ "do some tracing here" ].
>   ...
>
> but this always requires some message sends/checks if the debug mode is 
> active.
> This is OK while debugging/tracing to find errors - but for runtime one 
> whishes to have the
> best performance without any effect of tracing/debug code.
>
> Smalltalk/MT had a nice optimization feature that allowed to mix in debug 
> code without
> additional overhead when in non-debug mode. If I remember correctly the basic 
> idea was the
> following: there is a pool constant _DEBUG_INTERNAL that you compare to 
> another pool constant
> TRUE (representing the value 1).
>
> So with an expresion like _DEBUG_INTERNAL == TRUE this ends up in 1 == 1 
> comparision
> which is always true if the pool constants/values have the same value of 1.
> A followup message send of #ifTrue: will always be executed - therefore means 
> for the compiler
> to included the (debug) code:
>
> foo
>    ...
>    _DEBUG_INTERNAL == TRUE ifTrue: [
>        Processor outputDebugLine: 'Trace something'
>    ].
>    ...
>
> So in this case (always true) this was optimized by the compiler to
>
> foo
>    ...
>    Processor outputDebugLine: 'Trace something'
>    ...
>
> When _DEBUG_INTERNAL was set to FALSE (represented by value 0 as in C/C++) 
> this
> ends up in 0 == 1 which is always false and will never be true. So a followup 
> message
> send of #ifTrue: was optimized (removed as it was dead code and never 
> reached).
>
> foo
>    ...
>    ...
>
> So depending on pool flag _DEBUG_INTERNAL and recompilation of (all) methods 
> one
> could add debug/trace/logging code without runtime overhead. Yes this is very 
> C language
> like to have conditional compilation - but very effective in keeping 
> debug/tracing
> code influence low.
>
> I know we usually have the debugger in front of us - but sometimes a trace or 
> log is
> required to see where code crashes. Think of a headless situation in a 
> webserver or
> a small device like the pi where you want to reduce the performance overhead.
>
> This leads to several questions:
> - Is something like this feasible/already possible in Pharo?
> - Any pointers on how Opal does optimizations? Do we have similar 
> optimizations (removing
>   code that could not be reached) that could be used.
> - How do you usually deal with additional tracing code when you do not want to
>   have too much runtime overhead.

Does Pharo have pool *constants* or only pool *variables* ?  I don't
think a variable can/should affect compilation.

I like Eliot's approach of a variable holding a NullLogger, but if you
have expensive arguments to marshall and you need absolute
performance, perhaps an alternative proposal would be to consider
expanding the semantic that pragmas affect compilation, such that you
can use angle bracket blocks throughout the method that look up a
variable during compilation
   <compileThis: [Log this: 'error'] when: DebugFlag>

Another alternative may be to use MetaLinks to install & remove the
debugging code, plus something like the pragma syntax so these can be
written inline like this...
   myMethod
       x := y + 1.
       <  metalink: #debugging installWhenActive: [Log this: y]  >
       z := x + y.
Then you can enable debugging with...    MetaLink activate: #debugging.

cheers -ben

Reply via email to