[32723] in Perl-Users-Digest
Perl-Users Digest, Issue: 3987 Volume: 11
daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Thu Jul 11 18:14:32 2013
Date: Thu, 11 Jul 2013 15:14:06 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Perl-Users Digest Thu, 11 Jul 2013 Volume: 11 Number: 3987
Today's topics:
Re: this should work <ben@morrow.me.uk>
Re: this should work (Seymour J.)
Re: this should work (Seymour J.)
Re: this should work <rweikusat@mssgmbh.com>
Re: this should work <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>
Re: this should work <source@netcom.com>
Re: this should work <rweikusat@mssgmbh.com>
Re: this should work <kkeller-usenet@wombat.san-francisco.ca.us>
Re: this should work <jurgenex@hotmail.com>
Re: this should work <rweikusat@mssgmbh.com>
Re: this should work <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>
Re: this should work <derykus@gmail.com>
Re: this should work <ben@morrow.me.uk>
Re: this should work <ben@morrow.me.uk>
Re: this should work <ben@morrow.me.uk>
Re: this should work <ben@morrow.me.uk>
Re: this should work <ben@morrow.me.uk>
Re: this should work <rweikusat@mssgmbh.com>
Re: this should work <rweikusat@mssgmbh.com>
Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)
----------------------------------------------------------------------
Date: Thu, 11 Jul 2013 16:23:17 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: this should work
Message-Id: <58v2ba-u112.ln1@anubis.morrow.me.uk>
Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
> Ben Morrow <ben@morrow.me.uk> writes:
> > Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
> >> Jim Gibson <jimsgibson@gmail.com> writes:
> >>
> >> [...]
> >>
> >> > foreach my $dir (qw/commands_pre commands_post/) {
> >> > my $tmpdir = "/tmp/$dir";
> >> > print "$tmpdir\n"
> >> > }
> >>
> >> The perl compiler doesn't do invariant code motion because whether or
> >> not some code is 'invariant' cannot generally be decided at compile
> >> time.
> >
> > I don't know what you mean by that, but...
>
> In this case, this would be transforming the
>
> for (...) {
> my $tmp = 'ar!';
> }
>
> to
>
> my $tmp;
> for (...) {
> $tmp = 'ar!';
> }
>
> because the 'my $tmp' is invariant code: It's effective result never
> changes throughout the loop.
But it does: logically, you get a different variable each time. That
transformation changes the result, since the value of $tmp will persist
from one iteration to the next (as well as being visible below the
loop). Perl's runtime optimisation, which only kicks in if Perl can
prove it won't affect anything, is the only one possible.
> >> Because of this, the loop body above behave exactly as written
> >> down: For each iteration, it creates a new my variable and assigns a
> >> value to it.
> >
> > ...this is nonsense. Perl quite deliberately reuses the same variable
> > every time, to avoid the allocation overhead, unless you pass a (strong)
> > reference to it outside the loop. Try it and see:
> >
> > use Scalar::Util qw/refaddr/;
> >
> > for (1, 2, 3) {
> > my $tmp = "foo/$_";
> > say refaddr \$tmp;
> > }
>
> Maybe some versions of Perl do that (which would be an
> improvement). But the one I tested certainly doesn't.
Did you actually run that bit of code? With 'say' replaced with 'print',
it produces the same refaddr three times on every version perl I have
available (back to 5.6.0).
> Assuming the
> following code
>
> -------------
> use Benchmark;
>
> sub in_loop
> {
> for (0 .. 100) {
> my $a = $_ + 1;
> }
> }
>
> sub out_of_loop
> {
> my $a;
> for (0 .. 100) {
> $a = $_ + 1
> }
> }
>
> timethese(-2,
> {
> in_loop => \&in_loop,
> out_of_loop => \&out_of_loop
> });
> -------------
>
> the loop in in_loop is translated to (perl -MO=Concise,in_loop, perl
> 5.10.1)
>
> e <0> iter s ->f
> - <@> lineseq sK ->-
> 7 <;> nextstate(main 596 a.pl:6) v ->8
> c <2> sassign vKS/2 ->d
> a <2> add[t5] sK/2 ->b
> - <1> ex-rv2sv sK/1 ->9
> 8 <#> gvsv[*_] s ->9
> 9 <$> const[IV 1] s ->a
> b <0> padsv[$a:596,597] sRM*/LVINTRO ->c
> d <0> unstack s ->e
>
> [b] is what creates the variable.
>
> For out_of_loop, this looks like this:
>
> e <0> iter s ->f
> - <@> lineseq sK ->-
> 9 <;> nextstate(main 601 a.pl:14) v ->a
> c <2> add[$a:600,603] sK/TARGMY,2 ->d
> - <1> ex-rv2sv sK/1 ->b
> a <#> gvsv[*_] s ->b
> b <$> const[IV 1] s ->c
> d <0> unstack s ->e
>
> and the padsv ... LVINTRO happens in the subroutine preamble.
Ah yes, that's a *different* bit of cheating (on perl's part). The
'normal' way to compile C< $x = $_ + 1 > with a lexical $x would be
sassign
add[t2]
gvsv(*_)
const(IV 1)
padsv[$x]
(I've omitted the ex-rv2sv), and for the case with 'my' that is what
perl produces. It does much the same if $x is global:
sassign
add[t1]
gvsv(*_)
const(IV 1)
gvsv(*x)
regardless of whether this statement introduces $x or not, and if the
RHS is something other than a binary operator (say, a sub call):
sassign
entersub[t2]
pushmark
gv(*foo)
padsv[$x]
However, in the specific case of a builtin operator whose result is
assigned directly to an already-declared lexical, perl will optimise by
having the operator store its result directly in the lexical, rather
than using a temporary.
> Running the program here yields the expected result that out_of_loop
> executes at about 1.43 times the speed of in_loop.
Yeah, that's not surprising, given it's executing two fewer ops per
iteration; but this is because out_of_loop is exceptionally optimised,
rather than because in_loop is inherently inefficient. Run your
benchmark again with a sub call or something instead of the addition,
and I doubt you'll see any difference between the two.
The amount of extra work LVINTRO causes padsv to do is tiny. All it does
is flip a bit in the pad SV itself to mark it as being in scope, and
push a pad offset onto the save stack to cause it to be cleaned out
ready for the next iteration at the end of the scope.
Ben
------------------------------
Date: Thu, 11 Jul 2013 09:14:06 -0400
From: Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid>
Subject: Re: this should work
Message-Id: <51deaf9e$3$fuzhry+tra$mr2ice@news.patriot.net>
In <krkm21$19jd$1@news.ntua.gr>, on 07/11/2013
at 01:08 AM, "George Mpouras"
<nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam> said:
>foreach my $dir (qw/commands_pre commands_post/) {
>$dir = "/tmp/$dir";
>print "$dir\n"
>}
Please indent your code for readability.
># Modification of a read-only value attempted at ./test line 139
Are you saying that Perl should have caught your error but failed to
do so, or is that the (correct) error message from Perl?
--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>
Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to spamtrap@library.lspace.org
------------------------------
Date: Thu, 11 Jul 2013 09:10:04 -0400
From: Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid>
Subject: Re: this should work
Message-Id: <51deaeac$2$fuzhry+tra$mr2ice@news.patriot.net>
In <krm2ui$kif$1@news.ntua.gr>, on 07/11/2013
at 01:55 PM, George Mpouras
<nospam.gravitalsun.noadsplease@hotmail.noads.com> said:
>Perl is for humans so its behavior should be the expected if there is
> not a serious reason not to be
FSVO expected. Perl should conform to its documentation; changes to
documented behavior should only be made for good cause and after
serious consideration.
--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>
Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to spamtrap@library.lspace.org
------------------------------
Date: Thu, 11 Jul 2013 17:17:03 +0100
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: this should work
Message-Id: <87zjttax6o.fsf@sapphire.mobileactivedefense.com>
Ben Morrow <ben@morrow.me.uk> writes:
>> Ben Morrow <ben@morrow.me.uk> writes:
>> > Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
>> >> Jim Gibson <jimsgibson@gmail.com> writes:
>> >>
>> >> [...]
>> >>
>> >> > foreach my $dir (qw/commands_pre commands_post/) {
>> >> > my $tmpdir = "/tmp/$dir";
>> >> > print "$tmpdir\n"
>> >> > }
>> >>
>> >> The perl compiler doesn't do invariant code motion because whether or
>> >> not some code is 'invariant' cannot generally be decided at compile
>> >> time.
>> >
>> > I don't know what you mean by that, but...
>>
>> In this case, this would be transforming the
>>
>> for (...) {
>> my $tmp = 'ar!';
>> }
>>
>> to
>>
>> my $tmp;
>> for (...) {
>> $tmp = 'ar!';
>> }
>>
>> because the 'my $tmp' is invariant code: It's effective result never
>> changes throughout the loop.
>
> But it does: logically, you get a different variable each time. That
> transformation changes the result, since the value of $tmp will persist
> from one iteration to the next (as well as being visible below the
> loop).
It doesn't because the first thing which happens in the loop body is
an assignment overwriting the old value.
[...]
>> >> Because of this, the loop body above behave exactly as written
>> >> down: For each iteration, it creates a new my variable and assigns a
>> >> value to it.
>> >
>> > ...this is nonsense. Perl quite deliberately reuses the same variable
>> > every time, to avoid the allocation overhead, unless you pass a (strong)
>> > reference to it outside the loop. Try it and see:
>> >
>> > use Scalar::Util qw/refaddr/;
>> >
>> > for (1, 2, 3) {
>> > my $tmp = "foo/$_";
>> > say refaddr \$tmp;
>> > }
>>
>> Maybe some versions of Perl do that (which would be an
>> improvement). But the one I tested certainly doesn't.
>
> Did you actually run that bit of code? With 'say' replaced with 'print',
> it produces the same refaddr three times on every version perl I have
> available (back to 5.6.0).
Let me but it this way:
-------
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p;
p = malloc(8);
printf("%p\n", p);
free(p);
p = malloc(8);
printf("%p\n", p);
free(p);
return 0;
}
-------
This should usually print the same value twice despite, as can be
checked with ltrace (on Linux), it actually calls malloc and free
twice, IOW, that two entities which exists at two different times
happen to have the same address doesn't necessarily mean anything
except that they happen to have the same address.
>
>> Assuming the
>> following code
>>
>> -------------
>> use Benchmark;
>>
>> sub in_loop
>> {
>> for (0 .. 100) {
>> my $a = $_ + 1;
>> }
>> }
>>
>> sub out_of_loop
>> {
>> my $a;
>> for (0 .. 100) {
>> $a = $_ + 1
>> }
> }
>>
>> timethese(-2,
>> {
>> in_loop => \&in_loop,
>> out_of_loop => \&out_of_loop
>> });
>> -------------
>>
>> the loop in in_loop is translated to (perl -MO=Concise,in_loop, perl
>> 5.10.1)
>>
>> e <0> iter s ->f
>> - <@> lineseq sK ->-
>> 7 <;> nextstate(main 596 a.pl:6) v ->8
>> c <2> sassign vKS/2 ->d
>> a <2> add[t5] sK/2 ->b
>> - <1> ex-rv2sv sK/1 ->9
>> 8 <#> gvsv[*_] s ->9
>> 9 <$> const[IV 1] s ->a
>> b <0> padsv[$a:596,597] sRM*/LVINTRO ->c
>> d <0> unstack s ->e
>>
>> [b] is what creates the variable.
>>
>> For out_of_loop, this looks like this:
>>
>> e <0> iter s ->f
>> - <@> lineseq sK ->-
>> 9 <;> nextstate(main 601 a.pl:14) v ->a
>> c <2> add[$a:600,603] sK/TARGMY,2 ->d
>> - <1> ex-rv2sv sK/1 ->b
>> a <#> gvsv[*_] s ->b
>> b <$> const[IV 1] s ->c
>> d <0> unstack s ->e
>>
>> and the padsv ... LVINTRO happens in the subroutine preamble.
>
> Ah yes, that's a *different* bit of cheating (on perl's part).
No, it's not. It's a completely valid example of the difference
between '[needlessly] putting my into the loop' and 'my outside of the
loop':
[...]
> in the specific case of a builtin operator whose result is
> assigned directly to an already-declared lexical, perl will optimise by
> having the operator store its result directly in the lexical, rather
> than using a temporary.
[...]
> Run your benchmark again with a sub call or something instead of the
> addition, and I doubt you'll see any difference between the two.
I have no doubt that you will be able to find a way to transform the
code such that the difference I was writing about becomes unmeasurable
because it is tiny compared to the time 'accidental operations' also
performed in the loop need. However, 'a sub call' is not yet good
enough. But I see little reason to climb this ladder: Nobody ever
changed his opinion just because it was demonstrably wrong, only the
pseudo-arguments supposed to make it appear as the rational choice
nevertheless become more complicated.
------------------------------
Date: Thu, 11 Jul 2013 19:45:51 +0300
From: "George Mpouras" <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>
Subject: Re: this should work
Message-Id: <krmng9$2c8p$1@news.ntua.gr>
>> Are you saying that Perl should have caught your error but failed to
>> do so, or is that the (correct) error message from Perl?
What about if an error occure while perl is trying correctly to catch the
error and this fail ;
Joking, Perl correctly catches the error (of course it is not correct, that
this error correctly occured)
------------------------------
Date: Thu, 11 Jul 2013 10:02:56 -0700
From: David Harmon <source@netcom.com>
Subject: Re: this should work
Message-Id: <DZSdnaZ2Y-zBeEPMnZ2dnUVZ_gqdnZ2d@earthlink.com>
On Thu, 11 Jul 2013 10:32:41 +0100 in comp.lang.perl.misc, Rainer
Weikusat <rweikusat@mssgmbh.com> wrote,
>Jim Gibson <jimsgibson@gmail.com> writes:
>
>[...]
>
>> foreach my $dir (qw/commands_pre commands_post/) {
>> my $tmpdir = "/tmp/$dir";
>> print "$tmpdir\n"
>> }
>
>The perl compiler doesn't do invariant code motion because whether or
>not some code is 'invariant' cannot generally be decided at compile
>time. Because of this, the loop body above behave exactly as written
>down: For each iteration, it creates a new my variable and assigns a
>value to it. Unless there's a specific reason why this behaviour would
>be desirable, such constructs should be avoided[*].
Are you really proposing that the programmer should be expected to
write:
{
my $tmpdir;
foreach my $dir (qw/commands_pre commands_post/) {
$tmpdir = "/tmp/$dir";
print "$tmpdir\n"
}
}
------------------------------
Date: Thu, 11 Jul 2013 18:08:53 +0100
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: this should work
Message-Id: <87oba9ausa.fsf@sapphire.mobileactivedefense.com>
Rainer Weikusat <rweikusat@mssgmbh.com> writes:
[...]
> I have no doubt that you will be able to find a way to transform the
> code such that the difference I was writing about becomes
> unmeasurable
Just in case there's any doubt about that: Ben is - of course - right
in claiming that Perl doesn't really create a new variable if the
previously created one is still available for reuse, it just puts that
back into a 'virgin' state. Which is still more work then when the
variable has been created outside of the loop. Also, it is possible to
write code such that it exploits other side-effects of the 'new
variable perl loop' to make the difference more accentuated eg
-------------
use Benchmark;
sub three()
{
return "three";
}
sub in_loop
{
for (0 .. 100) {
my $a;
$a = three() if $_ & 1;
}
}
sub out_of_loop
{
my $a;
for (0 .. 100) {
$a = three() if $_ & 1;
}
}
timethese(-2,
{
in_loop => \&in_loop,
out_of_loop => \&out_of_loop
});
-------------
and it is - of course - also possible to 'enhance' perl to work around
stupidly written code harder in order to catch this as well. But
making the compiler work harder in order to hide someone's mistakes
better is still not exactly what I want to have given that the amount
of work the compiler performs is also a cost wich affects me.
------------------------------
Date: Thu, 11 Jul 2013 10:32:19 -0700
From: Keith Keller <kkeller-usenet@wombat.san-francisco.ca.us>
Subject: Re: this should work
Message-Id: <3q63bax8mr.ln2@goaway.wombat.san-francisco.ca.us>
On 2013-07-11, Rainer Weikusat <rweikusat@mssgmbh.com> wrote:
>
> In this case, this would be transforming the
>
> for (...) {
> my $tmp = 'ar!';
> }
>
> to
>
> my $tmp;
> for (...) {
> $tmp = 'ar!';
> }
>
> because the 'my $tmp' is invariant code: It's effective result never
> changes throughout the loop.
This strikes me as premature optimization. Unless I know my program is
spending too much time doing my $tmp = 'ar!'; inside the for loop, I
would much prefer to keep $tmp properly scoped and initialized inside
the loop.
--keith
--
kkeller-usenet@wombat.san-francisco.ca.us
(try just my userid to email me)
AOLSFAQ=http://www.therockgarden.ca/aolsfaq.txt
see X- headers for PGP signature information
------------------------------
Date: Thu, 11 Jul 2013 10:48:12 -0700
From: Jürgen Exner <jurgenex@hotmail.com>
Subject: Re: this should work
Message-Id: <5trtt89hnhie7louofsoj1rcn6sni77elg@4ax.com>
Keith Keller <kkeller-usenet@wombat.san-francisco.ca.us> wrote:
>On 2013-07-11, Rainer Weikusat <rweikusat@mssgmbh.com> wrote:
>> my $tmp;
>> for (...) {
>> $tmp = 'ar!';
>> }
>>
>> because the 'my $tmp' is invariant code: It's effective result never
>> changes throughout the loop.
>
>This strikes me as premature optimization. Unless I know my program is
>spending too much time doing my $tmp = 'ar!'; inside the for loop, I
>would much prefer to keep $tmp properly scoped and initialized inside
>the loop.
How very true!!!
CPU-time is cheap, programmers time is expensive.
jue
------------------------------
Date: Thu, 11 Jul 2013 18:48:17 +0100
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: this should work
Message-Id: <87k3kxasym.fsf@sapphire.mobileactivedefense.com>
Keith Keller <kkeller-usenet@wombat.san-francisco.ca.us> writes:
> On 2013-07-11, Rainer Weikusat <rweikusat@mssgmbh.com> wrote:
>>
>> In this case, this would be transforming the
>>
>> for (...) {
>> my $tmp = 'ar!';
>> }
>>
>> to
>>
>> my $tmp;
>> for (...) {
>> $tmp = 'ar!';
>> }
>>
>> because the 'my $tmp' is invariant code: It's effective result never
>> changes throughout the loop.
>
> This strikes me as premature optimization.
'Premature optimization' is a term which originally referred to the idea
of trying to write an 'optimal' machine-language programming 'from the
start', instead of concentrating on writing a working machine-language
program first and then - possibly - transform that into an
also-working but faster machine-language program and this in the
context of highly 'irregular' CISC-architecture as they were (still)
common in the 1970s where a lot of relatively 'bizarre' ways to
perform semantically identical operations in different ways actually
existed and it makes a hell lot of sense in this context.
It was never meant to be a universal justification for "But I don't
want to think about that!" and certainly also not for "But I don't
want to change my habits!"
> Unless I know my program is
> spending too much time doing my $tmp = 'ar!'; inside the for loop, I
> would much prefer to keep $tmp properly scoped and initialized inside
> the loop.
It is 'properly scoped' in the second example because the variable
stays (logically) alive for as long as it is going to be used and
'improperly scoped' in the first because (again, logically) it keeps
being destroyed and recreated (this is supposed to be a demonstration
that 'proper' means nothing on its own).
Unless you are having a serious out of memory problem,
'micro-optimizing' your code such that each object has the shortest
possible livetime can also be considered 'a premature optimization',
especially as it might not even help, as in this example.
------------------------------
Date: Thu, 11 Jul 2013 21:38:38 +0300
From: "George Mpouras" <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>
Subject: Re: this should work
Message-Id: <krmu3h$2tt4$1@news.ntua.gr>
+1000 !
------------------------------
Date: Thu, 11 Jul 2013 12:03:20 -0700
From: Charles DeRykus <derykus@gmail.com>
Subject: Re: this should work
Message-Id: <krmvhv$v3k$1@speranza.aioe.org>
On 7/11/2013 10:48 AM, Rainer Weikusat wrote:
> Keith Keller <kkeller-usenet@wombat.san-francisco.ca.us> writes:
>> On 2013-07-11, Rainer Weikusat <rweikusat@mssgmbh.com> wrote:
>>>
>>> In this case, this would be transforming the
>>>
>>> for (...) {
>>> my $tmp = 'ar!';
>>> }
>>>
>>> to
>>>
>>> my $tmp;
>>> for (...) {
>>> $tmp = 'ar!';
>>> }
>>>
...
>
> It is 'properly scoped' in the second example because the variable
> stays (logically) alive for as long as it is going to be used and
> 'improperly scoped' in the first because (again, logically) it keeps
> being destroyed and recreated (this is supposed to be a demonstration
> that 'proper' means nothing on its own).
But it (illogically) stays alive longer than is needed unless you insert
an additional, artificial scope as another poster showed:
{ my $tmp; for (...) { $tmp='ar!'} }.
[ And, of course, Ben's refaddr demo showed it really isn't "destroyed
and re-created". Digression: I seem to recall having seen a demo that
confirmed the older behavior once - it just printed \$tmp in lieu of
refaddr but the addr's differed each time and I could swear (almost) it
was newer than 5.6 ]
>
> Unless you are having a serious out of memory problem,
> 'micro-optimizing' your code such that each object has the shortest
> possible livetime can also be considered 'a premature optimization',
> especially as it might not even help, as in this example.
>
But, clearly, the narrowest possible scope for variables does help...
with potential variable collisions, havoc, and confusion in that
dangerous "no-man's land outside your own trench".
IMO, the insane optimization, is running a timing benchmark and
obsessing about microseconds of speed over hundreds, or more often
thousands, of iterations.
--
Charles DeRykus
------------------------------
Date: Thu, 11 Jul 2013 21:35:24 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: this should work
Message-Id: <chh3ba-va22.ln1@anubis.morrow.me.uk>
Quoth Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid>:
> In <krm2ui$kif$1@news.ntua.gr>, on 07/11/2013
> at 01:55 PM, George Mpouras
> <nospam.gravitalsun.noadsplease@hotmail.noads.com> said:
>
> >Perl is for humans so its behavior should be the expected if there is
> > not a serious reason not to be
>
> FSVO expected. Perl should conform to its documentation; changes to
> documented behavior should only be made for good cause and after
> serious consideration.
Perl should, in general, continue to behave in the way it has behaved in
the past. Changing the behaviour to match the documentation, rather than
the other way around, should only be done with good reason.
Ben
------------------------------
Date: Thu, 11 Jul 2013 22:02:51 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: this should work
Message-Id: <r4j3ba-va22.ln1@anubis.morrow.me.uk>
Quoth Charles DeRykus <derykus@gmail.com>:
>
> [ And, of course, Ben's refaddr demo showed it really isn't "destroyed
> and re-created". Digression: I seem to recall having seen a demo that
> confirmed the older behavior once - it just printed \$tmp in lieu of
> refaddr but the addr's differed each time and I could swear (almost) it
> was newer than 5.6 ]
If a reference to the variable still exists at the end of the loop, the
current instance is indeed removed from the pad and replaced with a
newly allocated instance. So in this case:
my @x;
for (1..10) {
my $x = "foo";
push @x, \$x;
}
say for map refaddr, @x;
the refaddrs will be different every time. Possibly this is what you are
remembering?
I'm fairly sure the reusing logic has been there since lexicals were
introduced in 5.000.
Ben
------------------------------
Date: Thu, 11 Jul 2013 21:48:33 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: this should work
Message-Id: <1ai3ba-va22.ln1@anubis.morrow.me.uk>
Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
> Ben Morrow <ben@morrow.me.uk> writes:
>
> > Run your benchmark again with a sub call or something instead of the
> > addition, and I doubt you'll see any difference between the two.
>
> I have no doubt that you will be able to find a way to transform the
> code such that the difference I was writing about becomes unmeasurable
> because it is tiny compared to the time 'accidental operations' also
> performed in the loop need.
I did not pick a sub call as an example because it is expensive, but
simply because entersub does not use a target and so cannot (easily) be
optimised to put its result directly into a lexical. If you compare
these two statements, for instance:
my $x;
$x = $_ = 1;
my $x = $_ = 1;
you will find the only difference is in the LVINTRO flag on the padsv;
the sassign/padsv combination is still required for the non-my case.
Ben
------------------------------
Date: Thu, 11 Jul 2013 21:58:25 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: this should work
Message-Id: <hsi3ba-va22.ln1@anubis.morrow.me.uk>
Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
> Keith Keller <kkeller-usenet@wombat.san-francisco.ca.us> writes:
> > On 2013-07-11, Rainer Weikusat <rweikusat@mssgmbh.com> wrote:
> >>
> >> because the 'my $tmp' is invariant code: It's effective result never
> >> changes throughout the loop.
> >
> > This strikes me as premature optimization.
>
> 'Premature optimization' is a term which originally referred to the idea
> of trying to write an 'optimal' machine-language programming 'from the
> start', instead of concentrating on writing a working machine-language
> program first and then - possibly - transform that into an
> also-working but faster machine-language program and this in the
> context of highly 'irregular' CISC-architecture as they were (still)
> common in the 1970s where a lot of relatively 'bizarre' ways to
> perform semantically identical operations in different ways actually
> existed and it makes a hell lot of sense in this context.
>
> It was never meant to be a universal justification for "But I don't
> want to think about that!" and certainly also not for "But I don't
> want to change my habits!"
This is not about habits: anyone who's been here (or anywhere else
programming is taught) for a while will know that getting beginners to
understand the value of proper scoping is not easy. It's about
cleanliness: the value assigned to $tmp is not needed outside of one
iteration of the loop, so it should not exist outside that scope.
> > Unless I know my program is
> > spending too much time doing my $tmp = 'ar!'; inside the for loop, I
> > would much prefer to keep $tmp properly scoped and initialized inside
> > the loop.
>
> It is 'properly scoped' in the second example because the variable
> stays (logically) alive for as long as it is going to be used and
> 'improperly scoped' in the first because (again, logically) it keeps
> being destroyed and recreated (this is supposed to be a demonstration
> that 'proper' means nothing on its own).
Yes, Humpty Dumpty, you can make words mean whatever you want; but that
doesn't change anything. The values in $tmp in the different iterations
of the loop are logically unrelated, so they should be in logically
distict variables; if perl in fact chooses to store them in the same
physical piece of memory this is an invisible optimisation.
> Unless you are having a serious out of memory problem,
> 'micro-optimizing' your code such that each object has the shortest
> possible livetime can also be considered 'a premature optimization',
> especially as it might not even help, as in this example.
Both the forms under discussion use exactly the same amount of memory at
all times (at least as long as $tmp only has an IV part), except for one
32bit value pushed onto the save stack.
Ben
------------------------------
Date: Thu, 11 Jul 2013 22:04:45 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: this should work
Message-Id: <d8j3ba-va22.ln1@anubis.morrow.me.uk>
Quoth "Newsgroup only please, address is no longer replyable." <bad@example.invalid>:
> On Thu, 11 Jul 2013 10:32:41 +0100 in comp.lang.perl.misc, Rainer
> Weikusat <rweikusat@mssgmbh.com> wrote,
> >Jim Gibson <jimsgibson@gmail.com> writes:
> >
> >[...]
> >
> >> foreach my $dir (qw/commands_pre commands_post/) {
> >> my $tmpdir = "/tmp/$dir";
> >> print "$tmpdir\n"
> >> }
> >
> >The perl compiler doesn't do invariant code motion because whether or
> >not some code is 'invariant' cannot generally be decided at compile
> >time. Because of this, the loop body above behave exactly as written
> >down: For each iteration, it creates a new my variable and assigns a
> >value to it. Unless there's a specific reason why this behaviour would
> >be desirable, such constructs should be avoided[*].
>
> Are you really proposing that the programmer should be expected to
> write:
>
> {
> my $tmpdir;
> foreach my $dir (qw/commands_pre commands_post/) {
> $tmpdir = "/tmp/$dir";
> print "$tmpdir\n"
> }
> }
This will, of course, be a good bit slower than with the my inside the
loop. Blocks are quite expensive, because they're one-iteration loops,
and that requires a bit of setup.
Ben
------------------------------
Date: Thu, 11 Jul 2013 23:06:31 +0100
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: this should work
Message-Id: <87txk0oioo.fsf@sapphire.mobileactivedefense.com>
Charles DeRykus <derykus@gmail.com> writes:
> On 7/11/2013 10:48 AM, Rainer Weikusat wrote:
>> Keith Keller <kkeller-usenet@wombat.san-francisco.ca.us> writes:
>>> On 2013-07-11, Rainer Weikusat <rweikusat@mssgmbh.com> wrote:
>>>>
>>>> In this case, this would be transforming the
>>>>
>>>> for (...) {
>>>> my $tmp = 'ar!';
>>>> }
>>>>
>>>> to
>>>>
>>>> my $tmp;
>>>> for (...) {
>>>> $tmp = 'ar!';
>>>> }
>>>>
>
> ...
>>
>> It is 'properly scoped' in the second example because the variable
>> stays (logically) alive for as long as it is going to be used and
>> 'improperly scoped' in the first because (again, logically) it keeps
>> being destroyed and recreated (this is supposed to be a demonstration
>> that 'proper' means nothing on its own).
>
> But it (illogically) stays alive longer than is needed unless you
> insert an additional, artificial scope as another poster showed:
The 'logically' was supposed to refer to the fact that perl employs
self-defense mechanisms against code of this type by NOT doing what
the author requested: It keeps the variable alive despite this seems
'ill/im' (arbitrary suffix attached) to some people: The computer has
been programmed to work around this obsession with the
'micro-optimized lifecycle management' (And this is a euphemism. I'd
wager a bet this this is practically just 'create a new variable
whenever you need one because remembering what variables were created
two lines ago would be SO cumbersome' [and 'plan in advance variables
will be needed' an imposition beyond any physically tolerable by
man]).
Do you think it was programmed to work around that because this is
such a great idea? I don't. Especially since the computer can only
work around the execution time penalty of this convention and not
against the mess in the source code ("which of the 1,375 $i I
encountered in the last 2000 lines of code is it this time?").
------------------------------
Date: Thu, 11 Jul 2013 23:08:28 +0100
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: this should work
Message-Id: <87ppuooilf.fsf@sapphire.mobileactivedefense.com>
Jürgen Exner <jurgenex@hotmail.com> writes:
> Keith Keller <kkeller-usenet@wombat.san-francisco.ca.us> wrote:
>>On 2013-07-11, Rainer Weikusat <rweikusat@mssgmbh.com> wrote:
>>> my $tmp;
>>> for (...) {
>>> $tmp = 'ar!';
>>> }
>>>
>>> because the 'my $tmp' is invariant code: It's effective result never
>>> changes throughout the loop.
>>
>>This strikes me as premature optimization. Unless I know my program is
>>spending too much time doing my $tmp = 'ar!'; inside the for loop, I
>>would much prefer to keep $tmp properly scoped and initialized inside
>>the loop.
>
> How very true!!!
> CPU-time is cheap, programmers time is expensive.
I originally also wrote about the problems this approach creates for
people who don't already know the code.
------------------------------
Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin)
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>
Administrivia:
To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.
Back issues are available via anonymous ftp from
ftp://cil-www.oce.orst.edu/pub/perl/old-digests.
#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.
------------------------------
End of Perl-Users Digest V11 Issue 3987
***************************************