Skip Menu |
Report information
Id: 130613
Status: open
Priority: 0/
Queue: perl6

Owner: Nobody
Requestors: alex6k [at] yahoo.com
Cc:
AdminCc:

Severity: (no value)
Tag: (no value)
Platform: (no value)
Patch Status: (no value)
VM: (no value)



Subject: [PERF] "if" without "else" much slower than "if" with empty "else"
From: Alex K <alex6k [...] yahoo.com>
To: "rakudobug [...] perl.org" <rakudobug [...] perl.org>
Date: Sat, 21 Jan 2017 19:44:17 +0000 (UTC)
Download (untitled) / with headers
text/plain 687b
Take a look at the following examples - the second is more than 10x(!!!) faster:

m: my int $i = 0; loop { if $i++ == 10_000_000 { last }}; say now - INIT now;
rakudo-moar f97d5c: OUTPUT«2.0606382␤»

m: my int $i = 0; loop { if $i++ == 10_000_000 { last } else {} }; say now - INIT now;
rakudo-moar f97d5c: OUTPUT«0.1727145␤»


In my understanding of https://github.com/rakudo/rakudo/blob/nom/src/Perl6/Actions.nqp#L1675 the first example is equivalent to:

m: my int $i = 0; loop { if $i++ == 10_000_000 { last } else { Empty } }; say now - INIT now;
rakudo-moar f97d5c: OUTPUT«WARNINGS for <tmp>:␤Useless use of constant value Empty in sink context (line 1)␤2.120407471␤»

RT-Send-CC: perl6-compiler [...] perl.org
On Sat, 21 Jan 2017 11:45:10 -0800, alex6k@yahoo.com wrote: Show quoted text
> Take a look at the following examples - the second is more than > 10x(!!!) faster: > m: my int $i = 0; loop { if $i++ == 10_000_000 { last }}; say now - > INIT now;rakudo-moar f97d5c: OUTPUT«2.0606382␤» > m: my int $i = 0; loop { if $i++ == 10_000_000 { last } else {} }; say > now - INIT now; > rakudo-moar f97d5c: OUTPUT«0.1727145␤» > > In my understanding of > https://github.com/rakudo/rakudo/blob/nom/src/Perl6/Actions.nqp#L1675 > the first example is equivalent to: > > m: my int $i = 0; loop { if $i++ == 10_000_000 { last } else { Empty } > }; say now - INIT now; > rakudo-moar f97d5c: OUTPUT«WARNINGS for <tmp>:␤Useless use of constant > value Empty in sink context (line 1)␤2.120407471␤»
That's because the two examples you are comparing are entirely different. The case with implicit or explicit Empty can be used in lists, in which the Empty slips away: <Zoffix> m: sub stuff { if 0 {} }; dd [1, stuff(), 4] <camelia> rakudo-moar 7f245f: OUTPUT«[1, 4]␤» But the explicit `else {}` results in a Nil, which leaves unwanted stuff in lists: <Zoffix> m: sub stuff { if 0 {} else {} }; dd [1, stuff(), 4] <camelia> rakudo-moar 7f245f: OUTPUT«[1, Any, 4]␤» --- So naturally, the optimizer can check whether whether the value of the conditional is ever used and avoid the Empty stuff, and it does so in some cases: <Zoffix> m: sub stuff { if 0 {} else {}; 42 }; for ^100_000 { $ = [1, stuff(), 4] }; say now - INIT now; <camelia> rakudo-moar 7f245f: OUTPUT«0.306001␤» <Zoffix> m: sub stuff { if 0 {}; 42 }; for ^100_000 { $ = [1, stuff(), 4] }; say now - INIT now; <camelia> rakudo-moar 7f245f: OUTPUT«0.3428267␤» It doesn't seem to do that for the OP case (even when you tack on an extra value after it so result isn't used). So perhaps it could be taught to do so. Note that I doubt you'd see much speedup from this in real-life code: "10 times" may sound impressive, but the average comes down to difference between 21.9 *nano*seconds vs 219 *nano*seconds.


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org