develooper Front page | perl.perl5.porters | Postings from January 2017

Re: [perl #78288] ref and other ops are inefficient in booleancontext

Thread Previous | Thread Next
From:
Dave Mitchell
Date:
January 3, 2017 13:22
Subject:
Re: [perl #78288] ref and other ops are inefficient in booleancontext
Message ID:
20170103132208.GT3096@iabyn.com
On Sat, Dec 31, 2016 at 04:09:30PM -0800, James E Keenan via RT wrote:
> On Fri, 08 Oct 2010 13:29:35 GMT, timbo wrote:
> > 
> > This is a bug report for perl from Tim.Bunce@pobox.com,
> > generated with the help of perlbug 1.39 running under perl 5.12.2.
> > 
> > 
> > -----------------------------------------------------------------
> > [Please describe your issue here]
> > 
> > [16:05] timbunce: code like "if ref $foo" is far more expensive than
> > it needs to be because ref() still creates a new SVPV when called in a
> > boolean context.
> > [16:08] xdg: timbunce, could you please open a ticket on that? I'm
> > sure someone can optimize that.
> > [16:10] • Nicholas wonders if "if ref $foo" can be spotted with much
> > the same code as "if %hash" is
> > [16:10] Zefram: yes it can, at op check time
> > [16:11] timbunce: How can internals determine "boolean context"?
> > [16:11] vincent: at op check time
> > [16:11] timbunce: there are probably other ops that could do less work
> > in boolean context
> > [16:11] Nicholas: offhand, "I don't know", but I know that "if %hash"
> > does this
> > 
> > [16:11] Zefram: but ref($foo)'s truth value isn't as simple as most
> > people expect, so it's approximately never what a programmer actually
> > wants
> > [16:12] timbunce: Zefram: true, but that doesn't stop people writing
> > "if ref $foo" often
> > [16:13] Zefram: I'd be more inclined to use check-time logic to emit a
> > warning for it
> > [16:14] Zefram: "Dubious use of reference-type operator in truth-value
> > context"
> > [16:14] timbunce: Zefram: I think you'd have angry hordes after you.
> > [16:14] timbunce: better done in perlcritic
> > [16:14] PerlJam: timbunce: +1
> > [16:14] mst: Zefram: but then Scalar::Defer won't work anymore
> > [16:14] Zefram: Scalar::Defer is an abomination
> >  [16:15] mst: Zefram: an abomination that's heavily used in the
> > pumpking's production code
> > [16:16] timbunce: mst Zefram: I think Scalar::Defer could still work.
> > The pp_ref code just needs to know if it should return sv_yes or sv_no
> > 
> > In boolean context, pp_ref would check the pv returned by sv_reftype
> > in
> > the same way that SvTRUE does (for "" and "0") and the push &sv_yes or
> > &sv_no.
> > 
> 
> Tim Bunce proposed this approach more than six years ago.
> 
> Can anyone respond?

I've just pushed the commit shown below as davem/boolref.
It shows that the concept is sound, but I suggest not merging into blead
until after 5.26.0 is released: even just setting an extra private flag on
an op may require various B-ish CPAN modules to be updated.

The repeep() code in my commit is separate from similar code that puts
rv2hv into boolean context in things like if (%h) {...}. I suspect they
want merging into a single function. I also noticed there's a bug in the
rv2hv stuff: if (!%h) {...} *doesn't* get optimised.

I'm open to suggestions for other ops which could benefit from being
special-cased in boolean context.

commit 9108e50fd89a88637207002130946c9c0b0ecc9d
Author:     David Mitchell <davem@iabyn.com>
AuthorDate: Tue Jan 3 12:08:08 2017 +0000
Commit:     David Mitchell <davem@iabyn.com>
CommitDate: Tue Jan 3 13:15:42 2017 +0000

    add an OPpREF_BOOL flag to OP_REF
    
    RT #78288
    
    When ref() is used in a boolean context, it's not necessary to return
    the name of the package which an object is blessed into; instead a simple
    truth value can be returned, which is faster.
    
    Note that it has to cope with the subtlety of an object blessed into the
    class "0", which should return false.
    
    Porting/bench.pl shows for the expression !ref($r), approximately:
        unchanged         for a non-reference $r
        doubling of speed for a reference $r
        tripling of speed for a blessed reference $r
    
    I haven't attempted to use a provisional boolean flag for when the
    expression's context isn't known at compile time (e.g. when used in the
    last expression in a sub), unlike the similar mechanism for rv2hv etc
    which has both OPpTRUEBOOL and OPpMAYBE_TRUEBOOL flags.


-- 
Fire extinguisher (n) a device for holding open fire doors.

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About