Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re^2: 4x faster now! (updated)

by h2 (Beadle)
on Jul 19, 2018 at 20:29 UTC ( [id://1218848]=note: print w/replies, xml ) Need Help??


in reply to Re: 4x faster now! (updated)
in thread Syntax Perl Version support $c = () = $a =~ /\./g

AnomalousMonk, re the speed up, I test using a loop, and to make it apples to apples, one version uses only regex to determine the numeric quality, and the other uses only tr/ + length.

AT 10k iterations, for a full valid number, the regex only version takes about 0.02 seconds, and the tr length version takes about 0.008 seconds. So i have to take back the 4x faster for tr y length, it's about 2.5x faster, because I had to add in a few more conditions to handle the length tests that failed for pre perl 5.012. Neither version is assigning any values to a variable. Since most things being tested are valid, this speed up is significant, albeit trivial in the larger sense.

That's for a full successful match, the times are of course less if it fails, though the order of the sequence of tests matters. I have bunch of variants of the below, but these roughly are apples to apples. Note that if I could have used only length($_[0]) instead of defined and length, that knocks a noticeable percent off the total, but as I learned, that test only became possible in Perl 5.012.

return 1 if (defined $_[0] && $_[0] =~ /^[\d\.]+$/ && $_[0] =~ /\d/ && + ( () = $_[0] =~ /\./g ) <= 1); return 1 if ( defined $_[0] && length($_[0]) == ($_[0] =~ tr/012345678 +9.//) && ( $_[0] =~ tr/0123456789//) >= 1 && ($_[0] =~ tr/.//) <= 1);

Generally the things I spend time testing and optimizing are core methods and tools that might actually knock milliseconds off execution time, which is something not super visible on new hardware, but quite noticeable on very old systems, low powered ARM devices, and so on. But I also like finding ways that are simply faster and more efficient in general, since the little things add up.

In both cases however the tests are much better than what I was using, since that allows non numeric numbers (/^[\d\.]+$/) like ..4.3. so both are improvements, but the tr version is roughly as fast as the original single but inaccurate regex, and is accurate. Thanks for the pointer to tr/ I would not have thought that ended up returning how many things it had found.

It was not so much the precedence that I discovered, but the fact that these tests actually also return a count of how many instances were replaced, for tr, or returned to fill an array that could then be counted as the total result of the statement that was something I was only faintly aware of as something that Perl does. I had used this feature without thinking much about it with things like if ($a = returns_something_or_nothing())... but I hadn't actually thought of that as a general principle that can be used for other things.

Replies are listed 'Best First'.
Re^3: 4x faster now! (updated)
by AnomalousMonk (Archbishop) on Jul 19, 2018 at 21:50 UTC

    Just out of curiosity, a couple more variations. Note that Scalar::Util::looks_like_number() thinks things like  +1  -1  2e3 look like numbers that you may not want to accept.

    c:\@Work\Perl\monks>perl -wMstrict -le "use Scalar::Util qw(looks_like_number); ;; use Data::Dump qw(pp); ;; for my $n ( undef, '', '.', '..', '.1.', '1..1', 0, '0', '0.', '0.0', '.0', '000.000', 1, '1', '1.', '1.0', '001.100', '+1', '-1', '2e3', ) { printf qq{%s %s like num \n}, pp($n), looks_like_number($n) ? 'looks' : 'does not look'; } " undef does not look like num "" does not look like num "." does not look like num ".." does not look like num ".1." does not look like num "1..1" does not look like num 0 looks like num 0 looks like num "0." looks like num "0.0" looks like num ".0" looks like num "000.000" looks like num 1 looks like num 1 looks like num "1." looks like num "1.0" looks like num "001.100" looks like num "+1" looks like num -1 looks like num "2e3" looks like num c:\@Work\Perl\monks>perl -wMstrict -le "sub unsigned_real { return defined($_[0]) && $_[0] =~ m{ \A (?: \d+ (?: [.] \d*)? | \d* [.] \d+) \z }xms ; } ;; use Data::Dump qw(pp); ;; for my $n ( undef, '', '.', '..', '.1.', '1..1', '+1', '-1', '2e3', 0, '0', '0.', '0.0', '.0', '000.000', 1, '1', '1.', '1.0', '001.100', ) { printf qq{%s %s real \n}, pp($n), unsigned_real($n) ? 'looks' : 'does not look'; } " undef does not look real "" does not look real "." does not look real ".." does not look real ".1." does not look real "1..1" does not look real "+1" does not look real -1 does not look real "2e3" does not look real 0 looks real 0 looks real "0." looks real "0.0" looks real ".0" looks real "000.000" looks real 1 looks real 1 looks real "1." looks real "1.0" looks real "001.100" looks real
    If the speed of any of these is acceptable, you will, of course, develop your own Test::More test suite(s). (But you'll want to do | you've already done that in any case. :)


    Give a man a fish:  <%-{-{-{-<

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1218848]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (2)
As of 2024-04-20 05:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found