guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: May nearly have simple statistical profiler working (need help).


From: Neil Jerram
Subject: Re: May nearly have simple statistical profiler working (need help).
Date: 15 Jul 2001 15:41:17 +0100
User-agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7

>>>>> "Neil" == Neil Jerram <address@hidden> writes:

>>>>> "Rob" == Rob Browning <address@hidden> writes:

    Rob> So what is the difference between apply-frame and
    Rob> enter-frame, and is the apply-frame handler guaranteed to be
    Rob> run for *every* function that's called?  Is apply-frame
    Rob> sufficient to catch all calls?

    Neil> As far as I understand, yes.

    Neil> One qualification on this: traps as a whole must be enabled
    Neil> for any of the trap handlers to be called.  This is
    Neil> controlled by `(debug-enable 'traps)' and the `with-traps'
    Neil> procedure.

Actually, having looked at your code, I see that this could be the
problem.  `(make-stack #t)' will give you a stack from the current
code position right back up to the most recent `(start-stack ...)'
expression.  For code executed from the REPL, this means everything
back up to the `(start-stack 'repl-stack ...)' in scm-style-repl/-eval
at line 2502 in boot-9.scm.

Apply frame traps, on the other hand, are active within the dynamic
scope of the `with-traps' expression in error-catching-loop at line
2268.  So, since

(top-repl)

-> (scm-style-repl)

-> (error-catching-repl ... -eval ...)

-> (error-catching-loop (lambda () ... -eval ...))

and since error-catching-loop only calls its thunk inside with-traps,
there will be a lot of applications for which the apply-frame trap
will fire but which you'll never see in the stack from (make-stack
#t).

Another thing is that the apply-frame trap dispatch mechanism disables
traps around the call to the trap handler.  So applications in and
below the trap handler won't trap themselves but could be seen in a
stack from (make-stack #t).

What you need is consistent stack narrowing.  Instead of `(make-stack
#t)', you can write `(make-stack #t INNER-PROC OUTER-PROC)'.
INNER-PROC and OUTER-PROC are both procedures, and then make-stack
basically cuts away all inner frames from the current code position up
to and including INNER-PROC, and all outer frames from the
`(start-stack ...)' down to and (I think) including OUTER-PROC.  (See
comments in stacks.c for more details.)

In fact I think you only need INNER-PROC.  In your
`profile-signal-handler', you should do `(make-stack #t
profile-signal-handler)' -- note that this obsoletes the
(caller-stack-num 2) hack.  Similarly, in `count-call', do
`(make-stack #t count-call)' rather than creating the stack from the
passed continuation.  Now you know that all your stacks extend from
`(start-stack 'repl-stack ...)' down to the innermost non-profiling
code.

Finally, to solve the problem of apply-frame traps inbetween
`with-traps' and `(start-stack 'repl-stack ...)', you could check in
the apply-frame handler that (eq? (stack-id #t) 'repl-stack).
(Outside 'repl-stack, I believe that (stack-id #t) returns #f.)

(In future you might want to provide an interface like
`(statprof-profile THUNK)' to do profiling for THUNK.  In this case,
you could use the OUTER-PROC to specify statprof-profile itself, or
perhaps THUNK; or you could start a new stack within the
implementation of statprof-profile: `(start-stack 'profile-stack
(THUNK))'.)

Best wishes,

        Neil

PS.  ISTR that Keisuke had some profiling code too; is your code
related to his?




reply via email to

[Prev in Thread] Current Thread [Next in Thread]