diff options
Diffstat (limited to 'lib/Memoize/t/speed.t')
-rwxr-xr-x | lib/Memoize/t/speed.t | 52 |
1 files changed, 44 insertions, 8 deletions
diff --git a/lib/Memoize/t/speed.t b/lib/Memoize/t/speed.t index d887aae60c..ef30a8138d 100755 --- a/lib/Memoize/t/speed.t +++ b/lib/Memoize/t/speed.t @@ -7,11 +7,28 @@ if (-e '.fast') { print "1..0\n"; exit 0; } +$| = 1; + +# If we don't say anything, maybe nobody will notice. +# print STDERR "\nWarning: I'm testing the speedup. This might take up to thirty seconds.\n "; -print "# Warning: I'm testing the speedup. This might take up to sixty seconds.\n"; print "1..6\n"; +# This next test finds an example that takes a long time to run, then +# checks to make sure that the run is actually speeded up by memoization. +# In some sense, this is the most essential correctness test in the package. +# +# We do this by running the fib() function with successfily larger +# arguments until we find one that tales at leasrtt $LONG_RUN seconds +# to execute. Then we memoize fib() and run the same call cagain. If +# it doesn't produce the same test in less than one-tenth the time, +# something is seriously wrong. +# +# $LONG_RUN is the number of seconds that the function call must last +# in order for the call to be considered sufficiently long. + + sub fib { my $n = shift; $COUNT++; @@ -19,20 +36,39 @@ sub fib { fib($n-1) + fib($n-2); } -$N = 0; +sub max { $_[0] > $_[1] ? + $_[0] : $_[1] + } + +$N = 1; $ELAPSED = 0; -until ($ELAPSED > 10) { - $N++; + +my $LONG_RUN = 10; + +while (1) { my $start = time; $COUNT=0; $RESULT = fib($N); $ELAPSED = time - $start; - print "# fib($N) took $ELAPSED seconds.\n" if $N % 1 == 0; + last if $ELAPSED >= $LONG_RUN; + if ($ELAPSED > 1) { + print "# fib($N) took $ELAPSED seconds.\n" if $N % 1 == 0; + # we'd expect that fib(n+1) takes about 1.618 times as long as fib(n) + # so now that we have a longish run, let's estimate the value of $N + # that will get us a sufficiently long run. + $N += 1 + int(log($LONG_RUN/$ELAPSED)/log(1.618)); + print "# OK, N=$N ought to do it.\n"; + # It's important not to overshoot here because the running time + # is exponential in $N. If we increase $N too aggressively, + # the user will be forced to wait a very long time. + } else { + $N++; + } } print "# OK, fib($N) was slow enough; it took $ELAPSED seconds.\n"; - +print "# Total calls: $COUNT.\n"; &memoize('fib'); @@ -48,12 +84,12 @@ print (($ELAPSED/$ELAPSED2 > 10) ? "ok 2\n" : "not ok 2\n"); print (($COUNT > $N) ? "ok 3\n" : "not ok 3\n"); # Do it again. Should be even faster this time. +$COUNT = 0; $start = time; $RESULT2 = fib($N); $ELAPSED2 = time - $start + .001; # prevent division by 0 errors - print (($RESULT == $RESULT2) ? "ok 4\n" : "not ok 4\n"); print (($ELAPSED/$ELAPSED2 > 10) ? "ok 5\n" : "not ok 5\n"); # This time it shouldn't have called the function at all. -print ($COUNT ? "ok 6\n" : "not ok 6\n"); +print ($COUNT == 0 ? "ok 6\n" : "not ok 6\n"); |