Re: map/array performance

2005-10-24 Thread Frank Bax

At 10:07 PM 10/23/05, Jeff 'japhy' Pinyan wrote:


On Oct 23, Frank Bax said:

   my $aval=''; map { $aval=$aval.sprintf(%4d,$aSuit{$a}{$_}); } 
@f_seq;


   my $aval=''; foreach $f (@f_seq) { 
$aval=$aval.sprintf(%4d,$aSuit{$a}{$f}); }


You should be using $aval .= here, instead of $aval = $aval .   And as 
John has shown, join() is even better.



Right, but I wasn't able to integrate sprintf and join together (I've 
figured it out since).  This code (from John) runs in 115 seconds (map was 
160, foreach was 195)!


my $format = '%4d' x @f_seq;
sprintf( $format, @{ $aSuit{ $a } }{ @f_seq } ) cmp sprintf( $format, 
@{ $aSuit{ $b } }{ @f_seq } );


THANKS - It has syntax elements that are new to me - I would never have 
come up with this on my own.



--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: map/array performance

2005-10-23 Thread John W. Krahn
Frank Bax wrote:
 Rather than create/store/sort many billion entities, my script creates
 these entities dynamically and maintains a hash of the top 100.  As
 each entity is created, I search my hash for the entity with lowest
 value, based on a number of elements in the hash; then low element
 gets replaced with new element.  Code looks like:
 my $low = 0;
 for( my $new=1; $new=$iSuit; ++$new ) {
 my $snew =
 sprintf(%4d%4d,$aSuit{$new}{'rescap'},$aSuit{$new}{'resval'});
 my $slow =
 sprintf(%4d%4d,$aSuit{$low}{'rescap'},$aSuit{$low}{'resval'});

Using sprintf() to concatenate numbers is (AFAIK) going to be slower than
concatenation:

my $snew = $aSuit{ $new }{ rescap } . $aSuit{ $new }{ resval };
my $slow = $aSuit{ $low }{ rescap } . $aSuit{ $low }{ resval };


 if( $snew lt $slow ) { $low = $new; }

You are comparing numbers so:

$low = $new if $snew  $slow;


 }
 I needed to change this code so that 'rescap' and 'resval' are runtime
 options and there could be any number of them, so I created an array
 @f_seq and rewrote my simple loop as:
 my $low = 0;
 for( my $new=1; $new=$iSuit; ++$new ) {
 $a=$new; $b=$low;
 if( cmpSuits()  0 ) { $low = $new; }
 }
   sub cmpSuits {
 my $aval=''; map { $aval=$aval.sprintf(%4d,$aSuit{$a}{$_}); } @f_seq;
 my $bval=''; map { $bval=$bval.sprintf(%4d,$aSuit{$b}{$_}); } @f_seq;

You shouldn't use map in void context, you should use a foreach loop instead,
but you don't even need a loop there:

my $aval = join '', @{ $aSuit{ $a } }{ @f_seq };
my $bval = join '', @{ $aSuit{ $b } }{ @f_seq };


 $bval cmp $aval;# ab=1  a=b=0  ab=-1 ... sorts descending

Or just:

join( '', @{ $aSuit{ $a } }{ @f_seq } ) cmp join( '', @{ $aSuit{ $b } }{
@f_seq } );


   }
 
 I use $a and $b because at the end of my script, aSuit hash is sorted
 for output - also using function cmpSuits.  The problem is that my
 script is now horribly slower than the original!!  Is this because I
 used map?  If so, what should I have used instead?
 
 Running the script on a small test sample from our database, the
 original code runs in 85-90 seconds.  The modified code using map,
 takes 160-165 seconds.  Processing of my real database took 69 hours
 on the original code, but at 80 hours, my modified script is not even
 half way!  I must find something a bit faster then map, but more
 flexible than my original code.

You might be able to use a Schwartzian Transform or a Guttman-Rosler Transform
to speed up the sort.



John
-- 
use Perl;
program
fulfillment

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: map/array performance

2005-10-23 Thread John W. Krahn
John W. Krahn wrote:
 Frank Bax wrote:
Rather than create/store/sort many billion entities, my script creates
these entities dynamically and maintains a hash of the top 100.  As
each entity is created, I search my hash for the entity with lowest
value, based on a number of elements in the hash; then low element
gets replaced with new element.  Code looks like:
my $low = 0;
for( my $new=1; $new=$iSuit; ++$new ) {
my $snew =
sprintf(%4d%4d,$aSuit{$new}{'rescap'},$aSuit{$new}{'resval'});
my $slow =
sprintf(%4d%4d,$aSuit{$low}{'rescap'},$aSuit{$low}{'resval'});
 
 Using sprintf() to concatenate numbers is (AFAIK) going to be slower than
 concatenation:
 
 my $snew = $aSuit{ $new }{ rescap } . $aSuit{ $new }{ resval };
 my $slow = $aSuit{ $low }{ rescap } . $aSuit{ $low }{ resval };

Sorry, that won't work because of the '%4d' format but this should:

   my $snew = $aSuit{ $new }{ rescap } * 1 + $aSuit{ $new }{ resval };
   my $slow = $aSuit{ $low }{ rescap } * 1 + $aSuit{ $low }{ resval };



John
-- 
use Perl;
program
fulfillment

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: map/array performance

2005-10-23 Thread Frank Bax

At 02:11 PM 10/23/05, John W. Krahn wrote:


Frank Bax wrote:
 my $snew =
 sprintf(%4d%4d,$aSuit{$new}{'rescap'},$aSuit{$new}{'resval'});
 my $slow =
 sprintf(%4d%4d,$aSuit{$low}{'rescap'},$aSuit{$low}{'resval'});

Using sprintf() to concatenate numbers is (AFAIK) going to be slower than
concatenation:

my $snew = $aSuit{ $new }{ rescap } . $aSuit{ $new }{ resval };
my $slow = $aSuit{ $low }{ rescap } . $aSuit{ $low }{ resval };

 my $aval=''; map { $aval=$aval.sprintf(%4d,$aSuit{$a}{$_}); } @f_seq;
 my $bval=''; map { $bval=$bval.sprintf(%4d,$aSuit{$b}{$_}); } @f_seq;

You shouldn't use map in void context, you should use a foreach loop instead,
but you don't even need a loop there:

my $aval = join '', @{ $aSuit{ $a } }{ @f_seq };
my $bval = join '', @{ $aSuit{ $b } }{ @f_seq };



Your suggested code changes don't work when the list of numbers on each 
side of comparison have different number of digits - that's why I initially 
introduced sprintf - so all numbers would use 4 
digits/characters.  Concatenate 284 and 9 to get 2849, 284 and 10 to get 
28410, which comes before 2849 in sting compare.  Using sprintf(%4d,...) 
-  284   9 is compared to  284  10 and works properly in this context.


What is void context? 



--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: map/array performance

2005-10-23 Thread Jeff 'japhy' Pinyan

On Oct 23, Frank Bax said:


At 02:11 PM 10/23/05, John W. Krahn wrote:


Frank Bax wrote:

 my $aval=''; map { $aval=$aval.sprintf(%4d,$aSuit{$a}{$_}); } 
@f_seq;
 my $bval=''; map { $bval=$bval.sprintf(%4d,$aSuit{$b}{$_}); } 
@f_seq;


You shouldn't use map in void context, you should use a foreach loop 


What is void context?


Void context means an expression whose return value is being discarded.

  $x = foo();  # scalar context
  @y = foo();  # list context
  foo();   # void context

map() builds a list to be returned, and by not USING its return value 
(that is, calling map() in void context), you're wasting resources.  If 
you do


  map BLOCK LIST

and don't intend on saving the return value of map(), just use a for loop.

  for (LIST) BLOCK

--
Jeff japhy Pinyan%  How can we ever be the sold short or
RPI Acacia Brother #734%  the cheated, we who for every service
http://www.perlmonks.org/  %  have long ago been overpaid?
http://princeton.pm.org/   %-- Meister Eckhart

--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: map/array performance

2005-10-23 Thread Frank Bax

At 04:35 PM 10/23/05, Frank Bax wrote:


At 02:11 PM 10/23/05, John W. Krahn wrote:


Frank Bax wrote:
 my $snew =
 sprintf(%4d%4d,$aSuit{$new}{'rescap'},$aSuit{$new}{'resval'});
 my $slow =
 sprintf(%4d%4d,$aSuit{$low}{'rescap'},$aSuit{$low}{'resval'});

Using sprintf() to concatenate numbers is (AFAIK) going to be slower than
concatenation:

my $snew = $aSuit{ $new }{ rescap } . $aSuit{ $new }{ resval };
my $slow = $aSuit{ $low }{ rescap } . $aSuit{ $low }{ resval };

 my $aval=''; map { $aval=$aval.sprintf(%4d,$aSuit{$a}{$_}); } 
@f_seq;
 my $bval=''; map { $bval=$bval.sprintf(%4d,$aSuit{$b}{$_}); } 
@f_seq;


You shouldn't use map in void context, you should use a foreach loop instead,
but you don't even need a loop there:

my $aval = join '', @{ $aSuit{ $a } }{ @f_seq };
my $bval = join '', @{ $aSuit{ $b } }{ @f_seq };



Your suggested code changes don't work when the list of numbers on each 
side of comparison have different number of digits - that's why I 
initially introduced sprintf - so all numbers would use 4 
digits/characters.  Concatenate 284 and 9 to get 2849, 284 and 10 to get 
28410, which comes before 2849 in sting compare.  Using sprintf(%4d,...) 
-  284   9 is compared to  284  10 and works properly in this context.



I just changed and tested:
my $aval=''; map { $aval=$aval.sprintf(%4d,$aSuit{$a}{$_}); } 
@f_seq;
my $bval=''; map { $bval=$bval.sprintf(%4d,$aSuit{$b}{$_}); } 
@f_seq;

to:
my $aval=''; foreach $f (@f_seq) { 
$aval=$aval.sprintf(%4d,$aSuit{$a}{$f}); }
my $bval=''; foreach $f (@f_seq) { 
$bval=$bval.sprintf(%4d,$aSuit{$b}{$f}); }


For my script foreach took 195 seconds, compared to 160 seconds using 
map.  We're headed in the wrong direction here!


FYI:  I added a counter to cmpSuit function - it gets called 14.2 million 
times on our small test database. 



--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: map/array performance

2005-10-23 Thread John W. Krahn
Frank Bax wrote:
 At 02:11 PM 10/23/05, John W. Krahn wrote:
 
 Frank Bax wrote:
  my $snew =
  sprintf(%4d%4d,$aSuit{$new}{'rescap'},$aSuit{$new}{'resval'});
  my $slow =
  sprintf(%4d%4d,$aSuit{$low}{'rescap'},$aSuit{$low}{'resval'});

 Using sprintf() to concatenate numbers is (AFAIK) going to be slower than
 concatenation:

 my $snew = $aSuit{ $new }{ rescap } . $aSuit{ $new }{ resval };
 my $slow = $aSuit{ $low }{ rescap } . $aSuit{ $low }{ resval };

  my $aval=''; map { $aval=$aval.sprintf(%4d,$aSuit{$a}{$_}); }
 @f_seq;
  my $bval=''; map { $bval=$bval.sprintf(%4d,$aSuit{$b}{$_}); }
 @f_seq;

 You shouldn't use map in void context, you should use a foreach loop
 instead,
 but you don't even need a loop there:

 my $aval = join '', @{ $aSuit{ $a } }{ @f_seq };
 my $bval = join '', @{ $aSuit{ $b } }{ @f_seq };
 
 
 Your suggested code changes don't work when the list of numbers on each
 side of comparison have different number of digits - that's why I
 initially introduced sprintf - so all numbers would use 4
 digits/characters.

my $format = '%4d' x @f_seq;
sprintf( $format, @{ $aSuit{ $a } }{ @f_seq } ) cmp sprintf( $format, @{
$aSuit{ $b } }{ @f_seq } );



John
-- 
use Perl;
program
fulfillment

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: map/array performance

2005-10-23 Thread Jeff 'japhy' Pinyan

On Oct 23, Frank Bax said:

   my $aval=''; map { $aval=$aval.sprintf(%4d,$aSuit{$a}{$_}); } 
@f_seq;


   my $aval=''; foreach $f (@f_seq) { 
$aval=$aval.sprintf(%4d,$aSuit{$a}{$f}); }


You should be using $aval .= here, instead of $aval = $aval .   And as 
John has shown, join() is even better.


--
Jeff japhy Pinyan%  How can we ever be the sold short or
RPI Acacia Brother #734%  the cheated, we who for every service
http://www.perlmonks.org/  %  have long ago been overpaid?
http://princeton.pm.org/   %-- Meister Eckhart

--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response