in reply to Re^4: Error handling in chained method calls
in thread Error handling in chained method calls

I wonder how.

From: perlapi:

gv_fetchmeth

Returns the glob with the given name and a defined subroutine or NULL . The glob lives in the given stash , or in the stashes accessible via @ISA and UNIVERSAL::.

The argument level should be either 0 or -1. If level==0 , as a side-effect creates a glob with the given name in the given stash which in the case of success contains an alias for the subroutine, and sets up caching info for this glob.

This function grants "SUPER" token as a postfix of the stash name. The GV returned from gv_fetchmeth may be a method cache entry, which is not visible to Perl code. So when calling call_sv , you should not use the GV directly; instead, you should use the method's CV, which can be obtained from the GV with the GvCV macro.

See also mro::invalidate_all_method_caches()


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
RIP an inspiration; A true Folk's Guy
  • Comment on Re^5: Error handling in chained method calls

Replies are listed 'Best First'.
Re^6: Error handling in chained method calls
by LanX (Saint) on Oct 24, 2010 at 21:08 UTC
    Wow, I'm impressed.

    An idealized benchmark shows only a 25% gain by memoizing, so I agree, it doesn't worth it.

    Rate classic memoized classic 75415/s -- -19% memoized 93110/s 23% --

    Cheers Rolf

      An idealized benchmark

      Hm. I'm not sure that "idealized" really described your benchmark. And neither does "memoized"--more like "hard-coded".

      Are you really suggesting that every user of every class should build a lexical cache of every method for each class they use, in each package they use it, and then hard-code all their method calls in terms of that lexical cache?

      I've removed your hard-coded version as unrealistic, and replaced with paranoid() reflecting the OPs suggested methodology. I've also added a realistically memoised version of that suggestion to show that it doesn't help:

      use strict; my $obj = Class->new; sub classic { $obj->meth0->meth1->meth2->meth3->meth4->meth5->meth6->meth7->meth8- +>meth9; } sub paranoid { $obj and ref $obj and my $ref0 = $obj->can('meth0'); $obj and ref $obj and my $ref1 = $obj->can('meth1'); $obj and ref $obj and my $ref2 = $obj->can('meth2'); $obj and ref $obj and my $ref3 = $obj->can('meth3'); $obj and ref $obj and my $ref4 = $obj->can('meth4'); $obj and ref $obj and my $ref5 = $obj->can('meth5'); $obj and ref $obj and my $ref6 = $obj->can('meth6'); $obj and ref $obj and my $ref7 = $obj->can('meth7'); $obj and ref $obj and my $ref8 = $obj->can('meth8'); $obj and ref $obj and my $ref9 = $obj->can('meth9'); $obj->$ref0->$ref1->$ref2->$ref3->$ref4->$ref5->$ref6->$ref7->$ref +8->$ref9; } my %memo; sub memoized { $obj and ref $obj and my $ref0 = $memo{ meth0 } || $obj->can('meth +0'); $obj and ref $obj and my $ref1 = $memo{ meth1 } || $obj->can('meth +1'); $obj and ref $obj and my $ref2 = $memo{ meth2 } || $obj->can('meth +2'); $obj and ref $obj and my $ref3 = $memo{ meth3 } || $obj->can('meth +3'); $obj and ref $obj and my $ref4 = $memo{ meth4 } || $obj->can('meth +4'); $obj and ref $obj and my $ref5 = $memo{ meth5 } || $obj->can('meth +5'); $obj and ref $obj and my $ref6 = $memo{ meth6 } || $obj->can('meth +6'); $obj and ref $obj and my $ref7 = $memo{ meth7 } || $obj->can('meth +7'); $obj and ref $obj and my $ref8 = $memo{ meth8 } || $obj->can('meth +8'); $obj and ref $obj and my $ref9 = $memo{ meth9 } || $obj->can('meth +9'); $obj->$ref0->$ref1->$ref2->$ref3->$ref4->$ref5->$ref6->$ref7->$ref +8->$ref9; } use Benchmark qw/cmpthese/; cmpthese(1E6, { classic => \&classic, paranoid => \&paranoid, memoized => \&memoized, }); package Class; sub new { bless {}, $_[0] } sub meth0 { $_[0] } sub meth1 { $_[0] } sub meth2 { $_[0] } sub meth3 { $_[0] } sub meth4 { $_[0] } sub meth5 { $_[0] } sub meth6 { $_[0] } sub meth7 { $_[0] } sub meth8 { $_[0] } sub meth9 { $_[0] } __END__ C:\test>junk Rate memoized paranoid classic memoized 101102/s -- -9% -65% paranoid 111099/s 10% -- -61% classic 286123/s 183% 158% --

      I was tempted to add a Moose example, but that would be just like bear-baiting.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        I was tempted to add a Moose example, but that would be just like bear-baiting.

        A Moose example wouldn't be any different because you are not hitting upon the places where Moose is slow. A method call in Moose is the same as a method call in a vanilla Perl object, and Moose does not override &can, seems like you are just trolling Moose again. Oh well.

        -stvn
        > An idealized benchmark

        > >Hm. I'm not sure that "idealized" really described your benchmark. And neither does "memoized"--more like "hard-coded".

        It's called a lower bound approximation.

        And BTW I also idealized by avoiding any inheritance.

        Cheers Rolf