Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

lightweight stack info

by hv (Prior)
on Jun 11, 2014 at 19:51 UTC ( [id://1089586]=perlquestion: print w/replies, xml ) Need Help??

hv has asked for the wisdom of the Perl Monks concerning the following question:

Is there existing art for capturing stack info (per Carp::longmess) that's lighter-weight than calling longmess?

At $work we annotate exceptions with a stacktrace so that we can ensure we log it for any exception that remains uncaught; we've been using that for a couple of years now, and it has been of huge benefit.

However a recent attempted CPAN module upgrade turned out to cause a huge performance degradation, which turned out to be because the module was using exceptions (in large numbers) as part of its normal processing, and the cost of the longmess() annotation suddenly becomes huge.

Given that the vast majority of these exceptions are caught, so never need a stacktrace logged, I'm now looking for a cheaper way to capture and attach the stacktrace info without going through the full serialization that longmess does. Kinda like a continuation, except we don't need to continue.

Thanks in advance for any suggestions.

Hugo

Replies are listed 'Best First'.
Re: lightweight stack info
by Your Mother (Archbishop) on Jun 11, 2014 at 22:40 UTC

    Is shortmess() out of the running? You can also do things like Carp::Clan to organize what's allowed to barf into the logs.

Re: lightweight stack info # wrong question?
by LanX (Saint) on Jun 12, 2014 at 01:35 UTC
    After reading your question multiple times, I realize that you were (IMHO) asking the wrong question.

    What you really need is an approach to restrict your logging to uncaught fatal errors only. (the cost of serialization does not matter than!)

    I would maybe try to patch the module in question, such that eval { BLOCK } is replaced by something disabling the die-handler.

    (and if you are lucky this module already uses something like Try::Tiny and you can restrict your patch there :)

    prove of concept:

    $SIG{__DIE__}= sub {warn "\$SIG{__DIE__} handles: $_[0]"; }; sub my_eval (&) { eval { local $SIG{__DIE__}; #deactivate die-handler $_[0]->(); } } warn "--- normal eval\n"; eval { die "EVAL\n" } or warn "Eval caught: $@\n"; warn "--- improved eval\n"; my_eval { die "MY_EVAL\n" } or warn "My_Eval caught: $@\n"; warn "--- top level die\n"; die "OUTER SCOPE\n";

    OUTPUT:

    --- normal eval $SIG{__DIE__} handles: EVAL Eval caught: EVAL --- improved eval My_Eval caught: MY_EVAL --- top level die $SIG{__DIE__} handles: OUTER SCOPE OUTER SCOPE Compilation exited abnormally with code 255 at Thu Jun 12 03:33:59

    It's hard to believe that you are the first having this problem, curious to here about other solutions now that the question is clearer.

    Cheers Rolf

    (addicted to the Perl Programming Language)

Re: lightweight stack info (data > text)
by tye (Sage) on Jun 12, 2014 at 04:53 UTC

    Personally, I'd just grab the file names, line numbers, and function names for the bottom 10 stack frames and do zero formatting. Just stuff those into a simple array. You can format those later only if the information needs to be shown.

    You can likely format the information better than Carp does because you know your specifics. For example, I don't want full paths for every single source file at work because most of them are going to start with /site/ourcorp/myproduct/version/lib/FOO, a long value whose repetition just makes it harder to read the useful information.

    I also don't want to see the attempts at abbreviating which arguments got passed to each function. If I really need that level of detail, then I'm going to build my own way of declaring "this is what is interesting about this particular call to this function" rather than hoping that an extremely terse summary of the top-level structure of each argument is even moderately informative.

    I would hope that such would be less of a performance impact than what Carp does. But I have not measured the difference. It might still be too slow for your case.

    - tye        

      Thanks, that's probably what I'll end up doing - after a good long think about what I'm capturing that's going to end up changing under my feet, or hanging onto a ref past its due dying date.

Re: lightweight stack info
by LanX (Saint) on Jun 11, 2014 at 23:07 UTC
    We just had a similar problem a day ago.

    Re: Bizarre Proc::Daemon error # die-handler

    I don't see a faster way to get the backtrace - only the possibility to filter out messages from the problematic module.(like already suggested)

    Either always check caller for the source (well you already got the backtrace anyway) or try to localize your die handler.

    If you are very desperate you can also try to write XS-code to speed up you're handler, but I think logging to the file system should be you're bottleneck°. (Did you already run benchmarks?)

    In this case logging to a DB could be an option.

    HTH! :)

    Cheers Rolf

    (addicted to the Perl Programming Language)

    update

    °) but after reading your question a third time, this doesn't seem to be the problem

Re: lightweight stack info
by cursion (Pilgrim) on Jun 11, 2014 at 21:00 UTC

    Check Perldoc Carp for info on shutting it off for parts of code (or only turning it on in your code).

    Maybe using caller() just when you do catch an exception could work too.

      Thanks; it'd certainly be possible to locally disable the annotation (a $SIG{__DIE__} handler, it isn't Carp internals we're talking about at this point) when we know we're going to call certain things; but that's not really the intended use - the idea is that for *any* exception that ends up not getting caught we want to know the call stack where it was raised: this is a mechanism for helping us become aware of and diagnose bugs we don't know about yet, and disabling it in some places means either asserting those sections of code are guaranteed bug-free, or just accepting that bugs in those sections of code will be harder to diagnose (and we may miss them altogether).

      As for doing the annotation at the point of catching: I don't think that helps us, we know what the call stack will look like at that point, it's what the call stack looked like at the point the exception was raised that's interesting.

      Hugo

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1089586]
Front-paged by GotToBTru
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (5)
As of 2024-03-28 13:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found