----- Original Message -----
Sent: Tuesday, September 13, 2005 11:01
AM
Subject: Re: regexp /o in a sub
Renard,
First, let me apologize for top-posting; we use Lotus
Notes and this is how it replies.
Now, someone else suggested something similar to your idea below, and I
am playing around with these ideas. But let me say this: the value of $row
(the selector in the for-do loop) is guaranteed to match one of the loop's
possibilities on each pass through the subroutine, so your fear of (what would
turn out to be) an infinite loop-ing is groundless. Also, some of the
possibilities--six, in fact--contain multiple lines of code. I don't know
enough Perl yet to handle these cases.
As a final obstacle, the HoH or AoH or whatever-of-whichever--the hash
that "reads" the others--proposed would have to be declared inside the sub,
after the variables $row and $val get their passed-in values. Question: would
94 "creations" of this 94-element data structure take more or less time than
the same number of passages through the for-do loop? And how would I handle
the six odd-balls mentioned above? Leave them out of the structure and process
them separately maybe? Suggestions, thoughts or advice?
Thanks,
Deane
I and the poster read enough of your abbreviated
code to get the
gest of what you seemed to do
... determine which hash to read and extract a
value
we apparently both missed that in some instances
youmight to just execute some code segment
so we both suggested using either a array of
hashes or an hash of hashes since we it would
more efficient than using a for loop. It could be
coded into lines and possibly one-liner
if you don't mind obscure code.
Now your abbreviated code had a line which
read: $out = "N/A";
This indicated that it was possible that fr some
value of $row a match would not found..
Hence my concern that a value of 101 would
require 102 passes through the loop...not an endless loop.
Not being a guru, I had a preconcieved
notion of what "for ($row) " would do.
I suspected that Translate() might not do
want you expected it to do.
So I wrote a small test script to verify my
suspision.
Here is the code:
#! perl
use warnings;
use
strict;
sub Translate
{
my ($row, $val) =
@_;
for ($row)
{
/^(5|6)$/o &&
do
{
print "$row - Will execute code segment A\n";
};
/^(2|4|7)$/o &&
do
{
print "$row - Will execute code segment B\n";
};
/^(0|1|3|8)$/o &&
do
{
print "$row - Will execute code segment C\n";
};
};
}
my $string = "whatever";
for (my $i = 0; $i <= 8;
$i++)
{
Translate($i,
$string);
}
Here the output
0 - Will execute code segment C
1 - Will execute code segment C
2 -
Will execute code segment B
3 - Will execute code segment C
4 - Will
execute code segment B
5 - Will execute code segment A
6 - Will execute
code segment A
7 - Will execute code segment B
8 - Will execute code
segment C
From this I concluded that for any valid value of $row the "for ($ow)^
would execute just one pass
therefore:
" last;" not necessary..."return $out;"
might be more appropriare if you really
are concerned about preventing tests that
will not find a match
no need for: $out = "N/A"; since you said that $row
will always be valid
I suspect that you had a "if elsif else" code structure before using the
"for" structure and found that a 3%
improvement. But is it a 3% improvement on code that cosumes a
significant portion of of program or only
lets 1% percent.
Now It has been my experience that the way you write the code
to be tested either inline or
as an anoymous subroutine can give conflicting results I have had
code that when written
inline Code A was faster than Code B and then when the code
segments
were writen as anonymous subroutine then Code A was slower than Code
B.
Now I suggest that before you worry about peaking the performance your
code that
1. complete the program, test it thoroughly.
2 if ir runs fast enough then let well enough alone
3 if it sluggish then use the profiler to find where the bottle neck
eists
4 concentrate on the code srgment that is slow
simplify the code ..the less it has to do the faster it will
run
it you find that you have to make the code more complex than
it becomes harder to maintain
5. dont bother to worry about using 'o' unless you really really really
not extact the last bit of
bit of performance ... most likely it will be a
waste of your time
Who cares if a script is faster by 1 millisecond or
even 10 milliseconds
|
| "renard"
<[EMAIL PROTECTED]>
09/12/2005 18:25
| To:
<[EMAIL PROTECTED]>,
<[email protected]> cc:
Subject: Re: regexp /o in a
sub |
----- Original
Message -----
From:
[EMAIL PROTECTED]
To: [email protected]
Sent: Monday, September 12, 2005 1:48 PM
Subject: regexp /o in a sub
Wizards,
Here's one for you. I'm doing some optimizing on a script (using
timethese and cmpthese calls in stub programs) and I was wondering about this.
I know the compile-once option on regular expressions has been maligned, but
I've found that it gets me about a 3% increase on one piece of code that uses
a for loop with regexps as a pseudo-switch statement (just like in the Camel
book). Here's what I'm working on (somewhat abbreviated):
sub Translate
{
my
($row, $val) = @_;
my $out = "";
for ($row)
{
/^(5|6|23|24|25|26|39|40|41|45|46|51|52|53|54|55|56|60|61|63|69|70|71|72|74|76)$/o
&& do
{
$out = $hashA( $val ) };
last;
};
/^(11|12|13|14|22|28|32|44|50|58|62|64|65|73|75|82|83|85|86|91|92|93)$/o
&& do
{
$out = $hashB{$val};
last;
};
/^(0|2|7|8|9|27|31)$/o && do
{
$out =
$val;
last;
};
/^(42|43|47|48|49|84)$/o && do
{
$out =
$hashC{$val};
last;
};
#
...
/^(57)$/o &&
do
{
$out =
$hashP{$val};
last;
};
/^(59)$/o
&& do
{
$out = $hashQ{$val};
last;
};
/^(81)$/o
&& do
{
$out = $hashR{$val};
last;
};
} # end for
($row)
$out = (length( $out ) > 0) ? $out :
"N/A"; # Default value for nulls
return( $row,
$out );
} # sub Translate()
All the
sub does is "translate" input to output using different hashes depending on
the index passed into the for loop.
There are 18 of these "switch" cases,
running from one to 26 OR-ed possibilities in the various cases. BUT, this
code is inside a subroutine, so here's the question: does using the /o on
these regexps inside a subroutine gain anything in runtime, as opposed to
using it in mainline code? What if the script is compiled, using perlapp, into
an executable? Is there any gain with /o then (either in mainline code or in a
sub) or does any gain go out the window once the code's compiled? If it
matters, the sub will get called 94 times per run of the script.
Thanks!
I am not a guru but the algorithm appears to be less than
optinum.
Of cours if is difficult to truly judge it since
the overall schme is not described
To me you seem to say that
you to:
use $row to determine which
hash to use to obtain the value from thst hash using the passed $value
as a key
1. you are trying to do 2 thing at one
time.
Perhaps you should consider creating an
array of hashes rather the a set of hashes
Now if the $row matches none of the values in your regex ... 99
then you will loop
through 99 times rather
than exiting after one pass
Now my approach would be to
do it in 2 steps.
Use hash where
the rows are the keys and values are the indexes of
the AoH
1 a one-liner can be written to to obtain an index
into the AoH
2. a one-liner can be written to use
the index and the $value (really a key) to obtain
your $out
Occam's Razor says that probably this is the better
solotion
Use the KISS principle Keep It Simple, I am
Stupid
Deane
P.S.:
Yes, I *do* have way too much time on my hands.... Why else would I be going
after such niggling improvements? ;->