in reply to Returning the lowest key in a hash (or highest)

Updated 2001/03/25 08:53:00 EST

I added the jcwren3 and jcwren4 tests which shows what happens when you remove the overhead of passing the 1000 element array around. It sort of makes that part of the comparison unfair, but when you're talking about being 24 times faster by not passing the array...

[jcw@linux jcw]$ perl q.pl Benchmark: running max_dkubb1, max_jcwren1, max_jcwren2, max_jcwren3, +max_jcwren4, max_tilly, each for at least 3 CPU seconds... max_jcwren1: 5 wallclock secs ( 2.95 usr + 0.05 sys = 3.00 CPU) @ 26 +010.00/s (n=78030) max_jcwren2: 6 wallclock secs ( 3.23 usr + 0.00 sys = 3.23 CPU) @ 90 +57.59/s (n=29256) max_jcwren3: 5 wallclock secs ( 3.00 usr + 0.00 sys = 3.00 CPU) @ 53 +767.33/s (n=161302) max_jcwren4: 5 wallclock secs ( 3.01 usr + 0.00 sys = 3.01 CPU) @ 11 +827.24/s (n=35600) max_dkubb1: 5 wallclock secs ( 3.00 usr + 0.00 sys = 3.00 CPU) @ 21 +65.67/s (n=6497) max_tilly: 5 wallclock secs ( 3.00 usr + 0.00 sys = 3.00 CPU) @ 17 +11.33/s (n=5134) [jcw@linux jcw]$

If doing in it Perl is fast, doing it in 'C' must be faster, right? Below is a comparison of two Inline methods. maxarray1 expects the list passed into it, whereas maxarray2 expects a reference. To my surprise, the first method is faster. I imagine that it's because the array doesn't have to be dereferenced for each element access. But that's for guys like tye, tilly, and chipmunk to tell me. Me, I don't know jack about Perl internals.

This *is* an example of knowing your data. Floating point values will fail miserably, since it expects a list of integers. But hey, if it's something you had to do a lot, you should optimize your routines for the expected data type. Flexibility is a Good Thing(tm), but it's expendable when you're looking for serious performance gains.

#!/usr/local/bin/perl -w use Algorithm::Numerical::Shuffle qw(shuffle); use Benchmark qw(timethese); #Randomize the array contents my @array = shuffle 0..1000; timethese(-3, { max_jcwren1 => sub { max_jcwren1(@array) }, max_jcwren2 => sub { max_jcwren2(@array) }, max_jcwren3 => sub { maxarray1(@array) }, max_jcwren4 => sub { maxarray2(\@array) }, max_dkubb1 => sub { max_dkubb1(@array) }, max_tilly => sub { max_tilly(@array) }, }); use Inline C => <<'END_OF_C_CODE'; int maxarray1(SV* array1, ...) { Inline_Stack_Vars; int max = 0; int i, j; for (i = 0; i < Inline_Stack_Items; i++) if ((j = (SvIV(Inline_Stack_Item(i)))) > max) max = j; return (max); } int maxarray2(SV* array_ref) { AV* array; int num_items; int max = 0; int i, j; if (! SvROK(array_ref)) croak("array_ref is not a reference"); array = (AV*)SvRV(array_ref); num_items = av_len(array); for (i = 0; i <= num_items; i++) if ((j = (SvIV(*av_fetch (array, i, 0)))) > max) max = j; return (max); } END_OF_C_CODE sub max_jcwren1 { return maxarray1 (@_); } sub max_jcwren2 { return maxarray2 (\@_); } sub max_dkubb1 { my $max = shift; $max < $_ and $max = $_ for @_; return $max; } sub max_tilly { my $max = shift; $max = $max < $_ ? $_ : $max for @_; return $max; }
--Chris

e-mail jcwren