Faster perl operation?

Alex LeDonne aledonne.listmail at gmail.com
Thu Jan 18 11:07:58 MST 2007


On 1/18/07, Joseph Sinclair <plug-discussion at stcaz.net> wrote:
> Joshua Zeidner wrote:
> > On 1/17/07, Jerry Davis <jdawgaz at cox.net> wrote:
> >>
> >> On Wednesday 17 January 2007 19:34, Kevin Brown wrote:
> >> > I'm working on a small script (so far only about 1000 lines long) and
> >> > I'm finding that I'd like a faster way to do:
> >> >
> >> > $variable = "." x ($start - 1);
> >> >
> >> > which is incredibly slow since it is creating sometimes on the order of
> >> > 100,000 to 3,000,000 (yes, Million) periods to fill up the needed
> >> string.
> >>
> >> if you do this more than once in the code, or in a loop;
> >> why don't you set up a variable at the top of your program that has the
> >> needed
> >> dots for the maximum number you would need -- lets say 3,000,000.
> >>
> >> then wherever you want n number of dots, just do $variable =
> >> substr($dots,
> >> 1,
> >> n). this should be much faster.
> >
> >
> >
> >  Jerry, I had the same idea, but are you sure that this operation will not
> > allocate a new buffer and copy the entire string( essentially eliminating
> > the benefit )?
> >
> >  jmz
> >
> ---
> It probably will.
>
> The simplest method I can think of to speed it up is to do something like this:
> $count = ($start - 1)
> $remainder = $count % 10000
> $base = "." x 10000
> $variable = $base x ($count / 10000)
> $tail = "." x $remainder
> $variable = $variable . $tail
>
> That should reduce the number of string reallocations by a factor of roughly 10,000.
>
> ==Joseph++
>

If you have to build a lot of these, I'd use more powers to get O(log
n) performance (I think). This wil work for up to 32,000,000+ dots,
and you only have the 24 string allocations in the array, and at most
24 for your dotstring.

-Alex

Lest there be any questions, this code (c) Alex LeDonne 2007, released
to the public domain. Free for any purpose including commercial use.

#!/usr/bin/perl
#
# Start by initializing our binary dot array
#
$bindots[0] = ".";

for ($i = 1; $i < 24; $i++) {
    $bindots[$i] = $bindots[$i-1] x 2;

}

#
# Now to convert a number to dots
# just use the binary representation
#
sub dottify ($) {
    my $num = $_[0];
    return "TOO BIG" if $num >= 2**24;

    my $returnstring;
    for ($i = 0; $i < 24; $i++) {
        if ($num & 2**$i) {   # this is a bitwise AND
            $returnstring .= $bindots[$i];
        }
    }
    return $returnstring
}

$dots_80 = dottify(80);
print "$dots_80\nPrinted 80 dots above.\n";

$dots_1919 = dottify(1919);
print "$dots_1919\nPrinted 1919 dots above, should be 1 dot shy of
filling\nan 80x24 terminal.\n";


More information about the PLUG-discuss mailing list