I've got a hash of anonymous subs that are called from within a large loop. A different one can be called each time. They look something like this:
package Foo; our %callbacks = ( pig => sub { ... }, cat => sub { ... }, dog => sub { ... } ); while (...) { # do stuff $choice = ...; $callbacks{$choice}->(@args); }
So if another class wants to extend Foo's functionality, they can just do this:
package main; use Foo; $Foo::callbacks{iguana} = sub { ... };
So far so good. But when I tried using -d:DProf to see which of these callbacks was being slow, I don't get anywhere because DProf doesn't help much with anonymous subs. All of them get lumped into one category, and I get something as uninformative as this:
%Time ExclSec CumulS #Calls sec/call Csec/c Name 90.73 0.770 0.648 60783 0.0000 0.0000 Foo::__ANON__
Although there is an option of dprofpp to split the __ANON__ subs into several lines, it still doesn't help me determine which one is the slow one (instead of all subs grouped into the __ANON__ category, I get __ANON__(28), __ANON__(3e), etc). I have to figure out which sub is which by looking at the #Calls column and making an educated guess.

It seems like the only way to get DProf to tell me what sub was called is to (obviously) have a named sub, and to call it by name, not just through a code reference. So I've had to resort to something like this, using symbolic references and fully-qualified sub names:

package Foo; sub Foo::callbacks::pig { ... } # no more hash! sub Foo::callbacks::cat { ... } sub Foo::callbacks::dog { ... } while (...) { # do stuff $choice = ...; # of course, we also validate $choice no strict 'refs'; &{"Foo::callbacks::$choice"}(@args); # I feel so dirty! } package main; ## now extend Foo by doing this: use Foo; sub Foo::callbacks::iguana { ... }
This actually works, and gives good information in DProf, but I'm wondering if this is the best way to get DProf to play nice with my anonymous subs... Also, is this a safe way to keep things, or should I switch back to the hash-based callbacks once I've profiled to my heart's content? Apart from the symbolic reference that I use to make the call, this approach seems reasonable to me.

The only "gotcha" I'm aware of is one that merlyn brought up in the CB a few days ago -- that SUPER:: won't work, as it's based on the package scope, not the actual name of the containing sub. However, there won't be any OO-things happening in these callbacks, and there's certainly no need to bless anyone into the Foo::callbacks namespace.

blokhead


In reply to Avoiding "Pkg::__ANON__" diagnostics with -d:DProf by blokhead

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.