monsieur_champs has asked for the wisdom of the Perl Monks concerning the following question:
Fellow Monks
First of all, this is not homework. I have a real problem behind this and can send full source code of my (unpublished) TWiki's MessageBoardPlugin if you want to see it.
My problem is optimization. I'm sure that using @_ instead of copying functions args to scopped variables is faster, and need to use this here:
# inputBox( $url, $msgid, $action, \%data )
sub inputBox{
my $data = $_[3];
# some code here...
# some processing here...
return $result . map this($_),
# hash de-ref and slicing at the same time...
# however, can't do this with $_[3], syntax error.
@$data{'a','b','c','d'};
I would like to use $_[3] instead of $data, but I can't, it generates a syntax error.
So what I need is a way to slice a de-referenced hash in just one shot. Any sugestions?
Thank you very much for your help.
Re: Trying to optimize de-referenced hash slice without scope variables...
by borisz (Canon) on Jun 15, 2004 at 17:15 UTC
|
write:
@{$_[3]}{'a','b','c','d'};
since perl reads it as @{$_}[3]{...} otherwise.
| [reply] [d/l] [select] |
|
perl -MData::Dumper -e "print Dumper @{$_[3]}{'a','b','c','d'}, $_[3];
+ "
$VAR1 = undef;
$VAR2 = undef;
$VAR3 = undef;
$VAR4 = undef;
$VAR1 = undef;
$VAR2 = undef;
$VAR3 = undef;
$VAR4 = undef;
$VAR1 = undef;
$VAR2 = undef;
$VAR3 = undef;
$VAR4 = undef;
$VAR5 = '1';
is the same thing as
perl -MData::Dumper -e 'print Dumper @$data{"a","b","c"}, $data'
$VAR1 = undef;
$VAR2 = undef;
$VAR3 = undef;
$VAR4 = {
'c' => undef,
'a' => undef,
'b' => undef
};
or I'm doing something really wrong here, or your data structure definition is not the same as my example. :-) Nice try, anyway.
| [reply] [d/l] [select] |
|
| [reply] [d/l] |
|
|
My perl works this way, Im sure there is another mistake.
#!/usr/bin/perl
use Data::Dumper;
%xx = ( a => 1, b => 2 );
sub inputBox{
@{$_[3]}{'a','b','c','d'};
}
sub inputBox2{
my $data = $_[3];
@$data{'a','b','c','d'};
}
print Dumper (inputBox( 1,2,3,\%xx));
print Dumper (inputBox2( 1,2,3,\%xx));
| [reply] [d/l] |
Re: Trying to optimize de-referenced hash slice without scope variables...
by Joost (Canon) on Jun 15, 2004 at 17:26 UTC
|
In addition to the post above, I would think that just copying one scalar is not that big a deal. Remember that you're copying only the hash reference, not the complete %data hash.
In fact, if you use $_[3] a lot in the same function, it might even be slower than copying it to a lexical variable, because of the array indexing that needs to be done. (haven't benchmarked this at all, so I might be wrong)
| [reply] [d/l] |
|
use strict;
use Benchmark qw(:all);
my %data = (
Lore =>'mipsumdo', ente =>'squemoll',
lors =>'itametco', isod =>'ioetnonu',
nsec =>'tetuerad', mmyf =>'acilisis',
ipis =>'cingelit', augu =>'eliberoi',
Sedr =>'honcusma', acul =>'isodioat',
ssai =>'dmollisp', cons =>'ectetuer',
hare =>'travelit', nisl =>'nislquis',
null =>'amattise', feli =>'sDonecma',
nimq =>'uisferme', gnar =>'isusulla',
ntum =>'nequenul', mcor =>'peridele',
lase =>'dduiDone', ifen =>'dutfeugi',
cbla =>'nditmetu', atas =>'emAliqua',
svit =>'aecondim', msed =>'magnaado',
entu =>'mluctusa', lorn =>'onummysa',
ntem =>'assaeuis', gitt =>'isNuncne',
moda =>'nteaport', corc =>'iMorbima',
amii =>'psumnonl', ttis =>'blandits',
eoAl =>'iquamcon', emPh =>'asellusq',
dime =>'ntumblan', uiso =>'rciInfer',
ditf =>'elisPell', ment =>'umturpis',
);
sub WithCopy {
my $hashref = $_[0];
my @dummy = @{$hashref}{'Lore','lors','nsec'};
}
sub WithoutCopy {
my @dummy = @{$_[0]}{'Lore','lors','nsec'};
}
cmpthese(5000000, {
'WithCopy' => 'WithCopy(\%data);',
'WithoutCopy' => 'WithoutCopy(\%data);',
});
__END__
Rate WithCopy WithoutCopy
WithCopy 548908/s -- -6%
WithoutCopy 581801/s 6% --
| [reply] [d/l] |
|
On my machine that gives (with 500000 iterations)
Rate WithCopy WithoutCopy
WithCopy 450450/s -- -9%
WithoutCopy 495050/s 10% --
But if you access the hashref more than once in the functions - say about 10 times:
use strict;
use Benchmark qw(:all);
my %data = (
Lore =>'mipsumdo', ente =>'squemoll',
lors =>'itametco', isod =>'ioetnonu',
nsec =>'tetuerad', mmyf =>'acilisis',
ipis =>'cingelit', augu =>'eliberoi',
Sedr =>'honcusma', acul =>'isodioat',
ssai =>'dmollisp', cons =>'ectetuer',
hare =>'travelit', nisl =>'nislquis',
null =>'amattise', feli =>'sDonecma',
nimq =>'uisferme', gnar =>'isusulla',
ntum =>'nequenul', mcor =>'peridele',
lase =>'dduiDone', ifen =>'dutfeugi',
cbla =>'nditmetu', atas =>'emAliqua',
svit =>'aecondim', msed =>'magnaado',
entu =>'mluctusa', lorn =>'onummysa',
ntem =>'assaeuis', gitt =>'isNuncne',
moda =>'nteaport', corc =>'iMorbima',
amii =>'psumnonl', ttis =>'blandits',
eoAl =>'iquamcon', emPh =>'asellusq',
dime =>'ntumblan', uiso =>'rciInfer',
ditf =>'elisPell', ment =>'umturpis',
);
sub WithCopy {
my $hashref = $_[0];
my @dummy1 = @{$hashref}{'Lore','lors','nsec'};
my @dummy2 = @{$hashref}{'Lore','lors','nsec'};
my @dummy3 = @{$hashref}{'Lore','lors','nsec'};
my @dummy4 = @{$hashref}{'Lore','lors','nsec'};
my @dummy5 = @{$hashref}{'Lore','lors','nsec'};
my @dummy6 = @{$hashref}{'Lore','lors','nsec'};
my @dummy7 = @{$hashref}{'Lore','lors','nsec'};
my @dummy8 = @{$hashref}{'Lore','lors','nsec'};
my @dummy9 = @{$hashref}{'Lore','lors','nsec'};
my @dummy0 = @{$hashref}{'Lore','lors','nsec'};
}
sub WithoutCopy {
my @dummy1 = @{$_[0]}{'Lore','lors','nsec'};
my @dummy2 = @{$_[0]}{'Lore','lors','nsec'};
my @dummy3 = @{$_[0]}{'Lore','lors','nsec'};
my @dummy4 = @{$_[0]}{'Lore','lors','nsec'};
my @dummy5 = @{$_[0]}{'Lore','lors','nsec'};
my @dummy6 = @{$_[0]}{'Lore','lors','nsec'};
my @dummy7 = @{$_[0]}{'Lore','lors','nsec'};
my @dummy8 = @{$_[0]}{'Lore','lors','nsec'};
my @dummy9 = @{$_[0]}{'Lore','lors','nsec'};
my @dummy0 = @{$_[0]}{'Lore','lors','nsec'};
}
cmpthese(500000, {
'WithCopy' => 'WithCopy(\%data);',
'WithoutCopy' => 'WithoutCopy(\%data);',
});
__END__
Rate WithoutCopy WithCopy
WithoutCopy 82645/s -- -8%
WithCopy 89445/s 8% --
Which seems to show that the performance increase is less when you index the @_ array a lot.
Of course it doesn't show that - it could also mean that the time needed to copy the keys of the hash reference 10 times overshadows the time needed to index the array and/or copy the hash reference, thereby decreasing the influence of doing either.
Benchmarking is hard.
| [reply] [d/l] [select] |
|
Interesting point. I use $data 8 times. Half as a boolean test (no de-reference) and half as a hash reference (to recover one or more values). I guess (and maybe I'm wrong about this) that it doesn't worth the benchmark...
Here is the complete function code:
sub inputBox{
# Don't uncomment, use @_ instead
# my $action_url = shift; # $_[0]
# my $msgid = shift; # $_[1]
# my $action = shift; # $_[2]
my $data = $_[3]; # oh, I needed this one, I wasn't able to use a ha
+sh-slice from a hash-reference in one shot.
<readmore>
return
qq{<form action="$_[0]" method="post">\n}.
($_[1]? qq{ <input type="hidden" name="message_id" value="$_[1]" />\n
+}:'').
qq{ <input type="hidden" name="action" value="$_[2]" />
<input type="hidden" name="commit" value="1" />
<table align="center" border="1" cellpadding="5" cellspacing="0">
<tr valign="middle" align="center" bgcolor="$color{TABLE_HEAD}">
<td colspan="2"> }
.($_[2] eq 'edit'? "Edit Message #$_[1]" : 'Compose New Message' ).
qq{ </td>
</tr>
<tr valign="middle" align="left" >
<td> Author: </td>
<td>
}.( $_[2] eq 'edit'? q{ <input type="text" name="author" size="
+40" }.
( $data? qq{value="$data->{author}"} : &TWiki::Func::getWikiUserName
+() )
. qq{ />} : &TWiki::Func::getWikiUserName() ) . q{
</td>
</tr>
<tr valign="middle" align="left">
<td>Due Date: </td>
<td>} . &gen_date_selector( 'due', ( $data? @$data{'day','month'
+,'year','hour','minute'} : (localtime)[5]+1900, (localtime)[4]+1, (lo
+caltime)[3], 23, 59 ) ) . qq{
</td>
</tr>
<tr valign="middle" align="left">
<td>Message: </td>
<td>
<textarea rows="5" name="msg" cols="50">}.($data? $data->{msg}
+ : '' ).qq{</textarea>
</td>
</tr>
<tr valign="middle" align="left">
<td>
<input type="checkbox" name="dropped" value="Y" }.($data && $d
+ata->{dropped} eq 'Y'? 'CHECKED':'' ).q{> Dropped.
</td>
<td align="right">
<input type="submit" name="change" value="Change Message">
</td>
</tr>
</table>
</form>
};
}
| [reply] [d/l] [select] |
Re: Trying to optimize de-referenced hash slice without scope variables...
by revdiablo (Prior) on Jun 15, 2004 at 20:55 UTC
|
Like Joost, I am a bit skeptical about the need for this "optimization." If the performance of your application hinges on the speed of accessing subroutine arguments, then I think Perl might not be the right choice. Have you done any profiling to see if this is the case, or are you simply stabbing in the dark? I suggest you do the former, rather than the latter, when it comes to expending time and effort to optimize your code.
| [reply] |
|
Dear fellow revdiablo
In fact, you're right about this: I'm stabbling in the dark.
But I'm not alone: this is a standard (?), required (?) optimization for TWiki Plugins like this and this.
Maybe I shall alert the main project developers about this "optimization".
Thank you for the insight.
| [reply] |
|
|