VMS specific cleanup and strictness for tie_sdbm.t
[p5sagit/p5-mst-13.2.git] / lib / Memoize / t / speed.t
CommitLineData
a0cb3900 1#!/usr/bin/perl
2
5317c87c 3BEGIN {
4 chdir 't' if -d 't';
5 @INC = '../lib';
6}
a0cb3900 7use Memoize;
573c37e8 8use strict;
9our $COUNT;
10our $RESULT;
a0cb3900 11
12if (-e '.fast') {
13 print "1..0\n";
14 exit 0;
15}
899dc88a 16$| = 1;
17
18# If we don't say anything, maybe nobody will notice.
19# print STDERR "\nWarning: I'm testing the speedup. This might take up to thirty seconds.\n ";
a0cb3900 20
3d4a255c 21sub times_to_time { my ($u) = times; $u; }
22if ($^O eq 'riscos') {
23 eval {require Time::HiRes; *my_time = \&Time::HiRes::time };
573c37e8 24 if ($@) { *my_time = sub { time }; }
3d4a255c 25} else {
26 *my_time = \&times_to_time;
27}
28
a0cb3900 29
30print "1..6\n";
31
3d4a255c 32
33
899dc88a 34# This next test finds an example that takes a long time to run, then
35# checks to make sure that the run is actually speeded up by memoization.
573c37e8 36# In some sense, this is the most essential correctness test in the package.
899dc88a 37#
573c37e8 38# We do this by running the fib() function with successively larger
39# arguments until we find one that takes at least $LONG_RUN seconds
899dc88a 40# to execute. Then we memoize fib() and run the same call cagain. If
41# it doesn't produce the same test in less than one-tenth the time,
42# something is seriously wrong.
43#
44# $LONG_RUN is the number of seconds that the function call must last
45# in order for the call to be considered sufficiently long.
46
47
a0cb3900 48sub fib {
49 my $n = shift;
50 $COUNT++;
51 return $n if $n < 2;
52 fib($n-1) + fib($n-2);
53}
54
573c37e8 55our $N = 1;
a0cb3900 56
573c37e8 57our $ELAPSED = 0;
899dc88a 58
59my $LONG_RUN = 10;
60
61while (1) {
a0cb3900 62 my $start = time;
63 $COUNT=0;
64 $RESULT = fib($N);
65 $ELAPSED = time - $start;
899dc88a 66 last if $ELAPSED >= $LONG_RUN;
67 if ($ELAPSED > 1) {
68 print "# fib($N) took $ELAPSED seconds.\n" if $N % 1 == 0;
69 # we'd expect that fib(n+1) takes about 1.618 times as long as fib(n)
70 # so now that we have a longish run, let's estimate the value of $N
71 # that will get us a sufficiently long run.
72 $N += 1 + int(log($LONG_RUN/$ELAPSED)/log(1.618));
73 print "# OK, N=$N ought to do it.\n";
74 # It's important not to overshoot here because the running time
75 # is exponential in $N. If we increase $N too aggressively,
76 # the user will be forced to wait a very long time.
77 } else {
573c37e8 78 $N++;
899dc88a 79 }
a0cb3900 80}
81
82print "# OK, fib($N) was slow enough; it took $ELAPSED seconds.\n";
899dc88a 83print "# Total calls: $COUNT.\n";
a0cb3900 84
85&memoize('fib');
86
87$COUNT=0;
573c37e8 88my $start = time;
89our $RESULT2 = fib($N);
90our $ELAPSED2 = (time - $start) || 1; # prevent division by 0 errors
a0cb3900 91
92print (($RESULT == $RESULT2) ? "ok 1\n" : "not ok 1\n");
93# If it's not ten times as fast, something is seriously wrong.
573c37e8 94print (($ELAPSED/$ELAPSED2 >= 10) ? "ok 2 - ELAPSED[$ELAPSED] ELAPSED2[$ELAPSED2]\n"
95 : "#
96# COUNT[$COUNT] N[$N] ELAPSED[$ELAPSED] ELAPSED2[$ELAPSED2]
97not ok 2\n");
a0cb3900 98# If it called the function more than $N times, it wasn't memoized properly
99print (($COUNT > $N) ? "ok 3\n" : "not ok 3\n");
100
101# Do it again. Should be even faster this time.
899dc88a 102$COUNT = 0;
a0cb3900 103$start = time;
104$RESULT2 = fib($N);
573c37e8 105$ELAPSED2 = (time - $start) || 1; # prevent division by 0 errors
a0cb3900 106
a0cb3900 107print (($RESULT == $RESULT2) ? "ok 4\n" : "not ok 4\n");
573c37e8 108print (($ELAPSED/$ELAPSED2 >= 10) ? "ok 5 - ELAPSED[$ELAPSED] ELAPSED2[$ELAPSED2]\n"
109 : "not ok 5\n");
a0cb3900 110# This time it shouldn't have called the function at all.
899dc88a 111print ($COUNT == 0 ? "ok 6\n" : "not ok 6\n");