[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]

infinite recursion in bignum->accuracy(123)



-----BEGIN PGP SIGNED MESSAGE-----

Moin,

this is a followup to:

http://groups.google.de/groups?selm=200211270314.gAR3Ed816177%40crypt.compul
ink.co.uk&oe=UTF-8&output=gplain

(please remove linebreak)

Below follows an adventure into bugland, along with explanations, and some
other comments. I also show other bugs in accuracy()/precision() and some
speedups. Anything shown here will appear in v1.65 (soon I hope). 

If you have little time, skip to the SUMMARY below, otherwise follow me.

Hugo wrote to me:

>Tels <perl_dummy@bloodgate.com> wrote:
>:Please try the latest debug snapshot of v1.65 at
>:http://bloodgate.com/perl/packages/devel/ and mail me the results. Thanx!
>
>Same recursion problem. Here's the short testcase:
>./perl -Ilib -Mbignum -wle 'bignum->accuracy(5); print bignum->accuracy'

Note: Actually, the print is not neccessary, it hangs at the accuracy()
call.

>This recurses in a loop around <bcmp, objectify, new, round>; after
>some tracking down with diagnostics, the problem seems to be the
>recursive attempt to upgrade in round(): the patch below gets me past
>that, and passes all tests.

Hugo dug around and did good work :)

>Of course you won't see this testing in isolation, since bignum isn't
>part of the same distribution. If you want to test new versions of MBI
>in the core, you may want to grab http://crypt.org/perl/module (and
'modules.txt' in the same place) which I use to automate the process
>of integrating a new version.

But actually I *do* see the bug in isolation, but not on my machine. The
reasons are explained below.

Here is Hugo's patch/fix (I "fixed" a wrapping line):

- --- Math-BigInt-1.65/lib/Math/BigInt.pm       Wed Nov 27 18:36:242002
+++ lib/Math/BigInt.pm  Thu Nov 28 10:42:54 2002
@@ -893,7 +893,7 @@
   $p = ${"$c\::precision"} unless defined $p;
  
   # A == 0 is useless, so undef it to signal no rounding
- -  $a = undef if defined $a && $a == 0;
+  $a = undef if !$a;
   
   # no rounding today? 
   return $self unless defined $a || defined $p;                # early out


Interesting to note is that both statements *should* be equivalent, so it
is quite strange to see this fixing the endless loop. 

But first more info:

        # perl -Mbignum -le 'print bignum->accuracy(42)'
        42
        # perl -Mbignum=v
        bignum                   v0.13
        Math::BigInt::Lite       v0.11
        Math::BigInt             v1.65 lib => Math::BigInt::Calc v0.34
        Math::BigFloat           v1.40

The reason I don't see the bug is Math::BigInt::Lite. So why does having
installed Math::BigInt::Lite or Hugo's patch fix it?

Some explanations on what happens:

When under use bignum; all constants are converted into Big* objects.
Usually this means BigInt for integers, and BigFloat for floats. However,
if you have Lite installed and the constant fits into a scalar,
Math::BigInt::Lite will be used, on the assumption that it is faster for
small numbers.

So, the culprit is:

        bignum->accuracy(5);

Note the '5'. if you write it like this with removed (non-installed) Lite,
you will get something like this:

        # perl -Mbignum -wle 'print bignum->accuracy(5)'
        Deep recursion on anonymous subroutine at
        /usr/local/lib/perl5/5.8.0/Math/BigInt.pm line 896.
        Deep recursion on subroutine "Math::BigInt::bcmp" at
        /usr/local/lib/perl5/5.8.0/Math/BigInt.pm line 70.
        Deep recursion on subroutine "Math::BigInt::objectify" at
        /usr/local/lib/perl5/5.8.0/Math/BigInt.pm line 963.
        Deep recursion on subroutine "Math::BigInt::new" at
        /usr/local/lib/perl5/5.8.0/Math/BigInt.pm line 2510.
        Deep recursion on subroutine "Math::BigInt::round" at
        /usr/local/lib/perl5/5.8.0/Math/BigInt.pm line 574.
        [hangs]

If you try this:

        # perl -Mbignum -wle 'print bignum->accuracy("5")'
        5

It works! The difference is that in the first case 5 get's converted
via Math::BigInt->new(5) to an object, it the latter case it stays as string
(and is used as numerical scalar value in accuracy()).

And why does giving an object to accuracy() make the code wander into
Recursive-Looping-Land? The reason is the "$a == 0" statement. Since $a
contains an object, overlord er overload kicks in, and calls
"$a->bcmp(0);". Which, unfortunately, uses ref($a)->new(0) to construct
another object from the second arg to compare it (highly inefficient, but
giving the circumstances the best we can do).

The first bcmp() then calls new() with some rounding parameters, and this
leads then to a loop (since new() uses round() which uses accuracy(); which
uses bcmp(), which uses new() etc etc). Or something like this. I think you
get the idea.

So, while Hugo's patch fixes the problem by avoiding to fall into the well,
it would be better if we fill the well and seal it.

A couple of solutions are possible:

 * comment round() and avoid using operations that lead to
   loops. That's what we didn't want to do. (Note: The same caveat occurs
   in accuracy() and probably elsewhere, so just avoiding it is a not good
   long term idea)
 * fiddle with new() and/or bcmp() and don't let it do rounding. Ugly, and
   probably not solvable without making everything slower. Definitely a
   no-go.
 * Doing away with objects in accuracy(), using scalars instead. This
   means scalars go to round(), which will thus not see objects. Hm.
   (For bonus points, do the same in round(), just To Be Sure[tm])

The last point sounds strange, because that would introduce a rather hard
limit into our BigInt world, where everything is an arbitrarily big number,
namely A or P beeing a scalar opposed to a BigNumber.

Well, that was a lie. Actually, round() already can only round in the range
of a scalar. This is for performance and practical reasons, like avoiding
infinitely deep recursion and thus even lower performance than you are used
to from BigInt and friends. :) So, the limitation is already build in.
(Also, Calc uses a Perl array to store a number, which also has a build-in
limit)

OTOH, if you try to round a number with more digits than a Perl scalar can
hold, you very probably have exhausted all memory on the system already :o)

(The same for BigFloats, but not counting trailing zeros. So 123e10000
actually has 3 digits as far as the rounding code is concerned, not 10003).

So, we just convert the argument in accuracy() (and precision(), while we
are at it) to a scalar. Interestingly, that not only fixes the bug, it also
makes it faster, and quite a bit!

SUMMARY
=======

The bug described at top is caused by the argument to accuracy() (or
precision) beeing an object. Now these are converted to scalars, which not
only fixes the bug, but also makes it faster.

While I was at this, I also noticed a couple of problems, which I fixed,
too.

 * accuracy() and precision() return undef when you set the global A or P,
   and then a local A or P and then try to unset the local A or P.
   Subsequent calls will return the A (or, you know it already, P) in
   effect for the local object, but the call to unset it does not. Testcode:

        use Test::More;
        use Math::BigInt;

        plan tests => 3;
        Math::BigInt->accuracy(42);
        my $x = Math::BigInt->new(123);         # $x gets A of 42, too!
        is ($x->accuracy(),42);                 # really?
        is ($x->accuracy(undef),42);            # $x has no A, but the
                                                # global is still in effect
                                                # for $x!
        is ($x->accuracy(),42);                 # so $x has still A = 42

   The second test will fail with versions up to v1.64. Not a big deal, but
   not right, either.
 * accuracy() (and it's evil twin, precision()) accept anything you
   throw at them, like floats, or garbage:

        #!/usr/bin/perl -w

        use Test::More;
        use Math::BigInt;

        plan tests => 1;
        isn't ($x->accuracy(4.2), '4.2', ' A must be integer');
        isn't ($x->accuracy('abc'), 'abc', 'A must be numeric');

   The last test actually dies with:

   Argument "abc" isn't numeric in numeric eq (==) at
   /usr/local/lib/perl5/5.8.0/Math/BigInt.pm line 229.
   accuracy must not be zero at /usr/local/lib/perl5/5.8.0/Math/BigInt.pm
   line 229.

   Dying is fine, but the famous last words should be correct.
 * Speaking of die(), it really should use Carp::croak.
 * bignum->accuracy(), bigint->accuracy() and bigrat->accuracy(), as well
   as their counter-parts named precision() call the BigInt/BigFloat
   routines one time too often just to get the proper return value.
   Saves us 1 of 3 (for bignum) respectively 1 of 2 calls in bigint/bigrat
   by just inserting a carefully placed "return ".
 * The fix from Hugo to round() should also be applied.

Things to do:

 * convert A and P arguments to round() to scalars as well?
 * when calling bround() or bfround() from accuracy() or precision(), it
   seems that bround() and bfround() are a bit inefficient in determing A or
   P they have to use. (namely, they try to find it out, instead just using
   the value they got just passed)

Anyone wishing to try out the fixed versions, please look for v1.64
(BigInt) and v0.14 (bignum) in:

        http://bloodgate.com/perl/packages/devel/

Attached are benchmarks results and the definitions file to generate them.
The benchmark used a v1.64 with Hugo's fix (to avoid endless loop).

Since in v1.39 the Math::BigInt->accuracy() syntax was broken, I used v1.45
as the first version to bench. Results are attached as absolute numbers
(operations/second) and relative to v1.45, 100 meaning as fast as v1.45,
200 twice as fast and so on.

The reason that Math::BigInt->precision(Math::BigInt->new(6)); got slower
(line 2 in precision benchmark) is that it converts the argument to a
scalar, which takes more time over just storing a ref to it. But it makes
using the precision later on much faster, which the benchmark doesn't show.
Also, typically you set the global A or P only once, but use it a lot. Since
accuracy() needs to check the argument for >= 0, setting the global one
actually got a lot faster (line 2 in accuracy benchmark). Using it later on
is also faster.

Also attached are two profiling runs of the following script:

        #!/usr/bin/perl -w
        use Math::BigInt;
        my $x = Math::BigInt->new(123);
        my $y = Math::BigInt->new(5);
        for (0..10000)
          {
          $x->accuracy($y);
          }

Which show the difference in the calling patterns. v1.64_fixed does
basically 36 calls (!) just for each $x->accuracy($y), while v1.65 needs
only 12 calls. Still too much, but better.

I hope to release v1.65 soon, please send me a lot of questions and
comments. Thanx in advance!

And thank you for listening to one of my boring emails :o)

Best wishes,

Tels


- -- 
perl -MMath::String -e 'print \
Math::String->from_number("215960156869840440586892398248"),"\n"'

 http://bloodgate.com/perl       My current Perl projects
 PGP key available on http://bloodgate.com/tels.asc or via email.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: When cryptography is outlawed, bayl bhgynjf jvyy unir cevinpl.

iQEVAwUBPe0TEncLPEOTuEwVAQGOGAf8CZ3cucKoj2U+e6oaiLJ4ah8En2oLdGEl
zi7/n86Tx+UwKycUkGmj0qd8CzlYka/LWNrCVAwQo0+ngsCHbuufzDJQ0PbjvKOb
t0w5XSUK5HKc9GTRv5cD1IeJO4Ze4WKkfYTgX01EypA1K6XWnYOm0FHkr39Hzb62
lZPr4EFGe4MZASi396REaY8M96UWuL7NyTKjzJfzF9iQmZV7SCuwwe5xhlORYro7
XDzYdeAlM3yx1cQiSIiPCp6T0JjHR0lv5l3lQLtGHZpYErt8MNjNSaf+rBBswND2
j00OQtkeEpjusSHWrEqPgsviLBNi0jgdUbKruDXQz0JaZrNLqxCONw==
=1qNO
-----END PGP SIGNATURE-----
Total Elapsed Time = 0.739378 Seconds
  User+System Time = 0.719378 Seconds
Exclusive Times
%Time ExclSec CumulS #Calls sec/call Csec/c  Name
 33.3   0.240  0.950  20002   0.0000 0.0000  Math::BigInt::accuracy
 29.1   0.210  0.630  10001   0.0000 0.0001  Math::BigInt::bround
 20.8   0.150  0.140  10001   0.0000 0.0000  Math::BigInt::numify
 19.4   0.140  0.140  10027   0.0000 0.0000  Math::BigInt::BEGIN
 16.6   0.120  0.110  10001   0.0000 0.0000  Math::BigInt::Calc::_len
 16.6   0.120  0.210  10001   0.0000 0.0000  Math::BigInt::length
 13.9   0.100  0.100  10001   0.0000 0.0000  Math::BigInt::is_zero
 5.56   0.040  0.100      1   0.0400 0.0997  main::BEGIN
 4.17   0.030  0.020  10001   0.0000 0.0000  Math::BigInt::Calc::_is_zero
 2.78   0.020  0.010  10001   0.0000 0.0000  Math::BigInt::_scale_a
 2.78   0.020  0.010  10001   0.0000 0.0000  Math::BigInt::Calc::_num
 2.78   0.020  0.010  10001   0.0000 0.0000  Math::BigInt::modify
 1.39   0.010  0.010      7   0.0014 0.0014  vars::BEGIN
 1.39   0.010  0.010      2   0.0050 0.0050  Exporter::as_heavy
 0.00   0.000 -0.000      3   0.0000      -  Exporter::import
 0.00   0.000 -0.000      1   0.0000      -  warnings::BEGIN
 0.00   0.000 -0.000      3   0.0000      -  warnings::register::import
 0.00   0.000 -0.000      6   0.0000      -  warnings::register::mkMask
 0.00   0.000 -0.000      5   0.0000      -  strict::import
 0.00   0.000 -0.000     20   0.0000      -  strict::bits
 0.00   0.000 -0.000      1   0.0000      -  overload::BEGIN
 0.00   0.000 -0.000      1   0.0000      -  overload::import
 0.00   0.000 -0.000      1   0.0000      -  overload::OVERLOAD
 0.00   0.000 -0.000      4   0.0000      -  constant::BEGIN
 0.00   0.000 -0.000     15   0.0000      -  strict::unimport
 0.00   0.000 -0.000      2   0.0000      -  constant::import
 0.00   0.000 -0.000      1   0.0000      -  Math::BigInt::TIESCALAR
 0.00   0.000 -0.000      7   0.0000      -  integer::import
 0.00   0.000 -0.000      1   0.0000      -  Math::BigInt::STORE
 0.00   0.000  0.030      1   0.0000 0.0299  Math::BigInt::import
 0.00   0.000  0.010      1   0.0000 0.0100  Exporter::export_to_level
 0.00   0.000 -0.000      2   0.0000      -  Exporter::Heavy::BEGIN
 0.00   0.000 -0.000      1   0.0000      -  Exporter::Heavy::heavy_export_to_l
                                     0.0000  evel
 0.00   0.000 -0.000      1   0.0000      -  Exporter::export
 0.00   0.000 -0.000      1   0.0000      -  Exporter::Heavy::heavy_export
 0.00   0.000 -0.000     11   0.0000      -  Math::BigInt::Calc::BEGIN
 0.00   0.000 -0.000      1   0.0000      -  integer::unimport
 0.00   0.000 -0.000      1   0.0000      -  Math::BigInt::Calc::_base_len
 0.00   0.000 -0.000      5   0.0000      -  Math::BigInt::Calc::_new
 0.00   0.000 -0.000      1   0.0000      -  Math::BigInt::Calc::import
Total Elapsed Time = 5.299253 Seconds
  User+System Time = 5.259253 Seconds
Exclusive Times
%Time ExclSec CumulS #Calls sec/call Csec/c  Name
 26.6   1.399  2.810  30004   0.0000 0.0001  Math::BigInt::new
 16.3   0.860  3.610  30002   0.0000 0.0001  Math::BigInt::objectify
 16.1   0.850  4.800  30002   0.0000 0.0002  Math::BigInt::bcmp
 10.6   0.560  0.540  20002   0.0000 0.0000  Math::BigInt::round
 10.6   0.560  0.540  20002   0.0000 0.0000  Math::BigInt::_split
 8.75   0.460  0.430  30002   0.0000 0.0000  Math::BigInt::Calc::_acmp
 8.37   0.440  0.410  30007   0.0000 0.0000  Math::BigInt::Calc::_new
 5.89   0.310  3.980  10001   0.0000 0.0004  Math::BigInt::bround
 4.18   0.220  4.960  30002   0.0000 0.0002  Math::BigInt::__ANON__
 3.04   0.160  0.170  10027   0.0000 0.0000  Math::BigInt::BEGIN
 2.66   0.140  0.160  10001   0.0000 0.0000  Math::BigInt::is_zero
 2.66   0.140  5.890  20002   0.0000 0.0003  Math::BigInt::accuracy
 2.28   0.120  0.110  10001   0.0000 0.0000  Math::BigInt::numify
 1.90   0.100  0.150  10001   0.0000 0.0000  Math::BigInt::length
 1.52   0.080  0.070  10001   0.0000 0.0000  Math::BigInt::Calc::_len
 1.14   0.060  0.050  20013   0.0000 0.0000  Math::BigInt::Calc::BEGIN
 1.14   0.060  0.050  10001   0.0000 0.0000  Math::BigInt::_scale_a
 0.95   0.050  0.040  10001   0.0000 0.0000  Math::BigInt::Calc::_is_zero
 0.76   0.040  0.100      1   0.0400 0.0997  main::BEGIN
 0.38   0.020  0.010  10001   0.0000 0.0000  Math::BigInt::Calc::_num
 0.38   0.020  0.010  10001   0.0000 0.0000  Math::BigInt::modify
 0.19   0.010  0.010      2   0.0050 0.0050  constant::import
 0.19   0.010  0.010      7   0.0014 0.0014  vars::BEGIN
 0.19   0.010  0.010      2   0.0050 0.0050  Exporter::as_heavy
 0.00   0.000 -0.000      3   0.0000      -  Exporter::import
 0.00   0.000 -0.000      1   0.0000      -  warnings::BEGIN
 0.00   0.000 -0.000      3   0.0000      -  warnings::register::import
 0.00   0.000 -0.000      6   0.0000      -  warnings::register::mkMask
 0.00   0.000 -0.000      5   0.0000      -  strict::import
 0.00   0.000 -0.000     20   0.0000      -  strict::bits
 0.00   0.000 -0.000      1   0.0000      -  overload::BEGIN
 0.00   0.000 -0.000      1   0.0000      -  overload::import
 0.00   0.000 -0.000      1   0.0000      -  overload::OVERLOAD
 0.00   0.000 -0.000      4   0.0000      -  constant::BEGIN
 0.00   0.000 -0.000     15   0.0000      -  strict::unimport
 0.00   0.000 -0.000      1   0.0000      -  Math::BigInt::TIESCALAR
 0.00   0.000 -0.000      7   0.0000      -  integer::import
 0.00   0.000 -0.000      1   0.0000      -  Math::BigInt::STORE
 0.00   0.000  0.030      1   0.0000 0.0299  Math::BigInt::import
 0.00   0.000  0.010      1   0.0000 0.0100  Exporter::export_to_level
BigBench v0.09  (c) Copyright by Tels 2001-2002.  Have fun!

Tue Dec  3 21:11:23 2002 Reading templates from 'v1.65-test//'...done.
 Got 2 templates.
Tue Dec  3 21:11:23 2002 Reading definitions from def/accuracy.def...done.
 Got 20 ops in 2 groups.

Each op will run for at least 2 seconds.
Results are scaled by factor 1 and rounded to 3 digits.
Results will be rounded to integer.
The benchmark will run for approximately 3 minutes.

Running 'v1.64_fixed':
 Benchmarking group 1 ('accuracy'):
      1  global scalar 5      102000 ops/s
      2  global bigint 5        3860 ops/s
      3  123 ()               156000 ops/s
      4  123 undef            110000 ops/s (empty: 36100, both: 27100)
      5  123 scalar 5          14200 ops/s (empty: 35900, both: 10200)
      6  123 bigint 5           2150 ops/s (empty: 210000, both: 2130)
      7  12345 scalar 2         8560 ops/s (empty: 36100, both: 6920)
      8  12345 bigint 2         2020 ops/s (empty: 36100, both: 1910)
 Average:                      49800 ops/s
 Benchmarking group 2 ('precision'):
      9  global scalar 5      107000 ops/s
     10  global bigint 5      103000 ops/s
     11  123 ()               159000 ops/s
     12  123 undef            121000 ops/s (empty: 35700, both: 27600)
     13  123 scalar -5         27200 ops/s (empty: 35900, both: 15500)
     14  123 bigint -5          5080 ops/s (empty: 35000, both: 4440)
     15  12345 scalar -2       27900 ops/s (empty: 35200, both: 15600)
     16  12345 bigint -2        5120 ops/s (empty: 35900, both: 4480)
     17  123 scalar 5           6190 ops/s (empty: 35600, both: 5270)
     18  123 bigint 5           1300 ops/s (empty: 35700, both: 1260)
     19  12345 scalar 2         6310 ops/s (empty: 35900, both: 5360)
     20  12345 bigint 2         1270 ops/s (empty: 35200, both: 1230)
 Average:                      47600 ops/s

Running 'v1.65':
 Benchmarking group 1 ('accuracy'):
      1  global scalar 5       92900 ops/s
      2  global bigint 5       34000 ops/s
      3  123 ()               159000 ops/s
      4  123 undef             79000 ops/s (empty: 36400, both: 24900)
      5  123 scalar 5          14100 ops/s (empty: 36100, both: 10200)
      6  123 bigint 5           8550 ops/s (empty: 215000, both: 8220)
      7  12345 scalar 2         8490 ops/s (empty: 36400, both: 6890)
      8  12345 bigint 2         7090 ops/s (empty: 36400, both: 5930)
 Average:                      50300 ops/s
 Benchmarking group 2 ('precision'):
      9  global scalar 5      105000 ops/s
     10  global bigint 5       39100 ops/s
     11  123 ()               159000 ops/s
     12  123 undef             83600 ops/s (empty: 36400, both: 25400)
     13  123 scalar -5         27900 ops/s (empty: 36200, both: 15800)
     14  123 bigint -5         17800 ops/s (empty: 35500, both: 11900)
     15  12345 scalar -2       28100 ops/s (empty: 36200, both: 15800)
     16  12345 bigint -2       17300 ops/s (empty: 36400, both: 11700)
     17  123 scalar 5           6230 ops/s (empty: 36400, both: 5320)
     18  123 bigint 5           5480 ops/s (empty: 36200, both: 4760)
     19  12345 scalar 2         6280 ops/s (empty: 36000, both: 5350)
     20  12345 bigint 2         5540 ops/s (empty: 36600, both: 4810)
 Average:                      41800 ops/s

Tue Dec  3 21:15:07 2002 Numbers are relative to v1.64_fixed, 100 denotes 100%.

                  |  v1.65
 -----------------+--------
  global scalar 5 |   91.0
  global bigint 5 |    881
  123 ()          |    102
  123 undef       |   72.0
  123 scalar 5    |   99.0
  123 bigint 5    |    398
  12345 scalar 2  |   99.0
  12345 bigint 2  |    351
 accuracy:        |    101
 .................|........
  global scalar 5 |   98.0
  global bigint 5 |   38.0
  123 ()          |    100
  123 undef       |   69.0
  123 scalar -5   |    103
  123 bigint -5   |    350
  12345 scalar -2 |    101
  12345 bigint -2 |    338
  123 scalar 5    |    101
  123 bigint 5    |    422
  12345 scalar 2  |    100
  12345 bigint 2  |    436
 precision:       |   87.8
 .................|........

Tue Dec  3 21:15:07 2002 All done. Enjoy!

BigBench v0.09  (c) Copyright by Tels 2001-2002.  Have fun!

Tue Dec  3 21:07:24 2002 Reading templates from 'v1.65-test//'...done.
 Got 2 templates.
Tue Dec  3 21:07:24 2002 Reading definitions from def/accuracy.def...done.
 Got 20 ops in 2 groups.

Each op will run for at least 2 seconds.
Results are scaled by factor 1 and rounded to 3 digits.
Results will be rounded to integer.
The benchmark will run for approximately 3 minutes.

Running 'v1.64_fixed':
 Benchmarking group 1 ('accuracy'):
      1  global scalar 5      104000 ops/s
      2  global bigint 5        3900 ops/s
      3  123 ()               158000 ops/s
      4  123 undef            112000 ops/s (empty: 35900, both: 27200)
      5  123 scalar 5          14300 ops/s (empty: 35800, both: 10200)
      6  123 bigint 5           2130 ops/s (empty: 210000, both: 2110)
      7  12345 scalar 2         8660 ops/s (empty: 35200, both: 6950)
      8  12345 bigint 2         2030 ops/s (empty: 35500, both: 1920)
 Average:                      50700 ops/s
 Benchmarking group 2 ('precision'):
      9  global scalar 5      106000 ops/s
     10  global bigint 5      103000 ops/s
     11  123 ()               159000 ops/s
     12  123 undef            115000 ops/s (empty: 36100, both: 27400)
     13  123 scalar -5         27600 ops/s (empty: 35700, both: 15600)
     14  123 bigint -5          5070 ops/s (empty: 35700, both: 4440)
     15  12345 scalar -2       27300 ops/s (empty: 36000, both: 15500)
     16  12345 bigint -2        5110 ops/s (empty: 35300, both: 4460)
     17  123 scalar 5           6220 ops/s (empty: 35300, both: 5290)
     18  123 bigint 5           1310 ops/s (empty: 35700, both: 1260)
     19  12345 scalar 2         6320 ops/s (empty: 35800, both: 5370)
     20  12345 bigint 2         1250 ops/s (empty: 35400, both: 1210)
 Average:                      46900 ops/s

Running 'v1.65':
 Benchmarking group 1 ('accuracy'):
      1  global scalar 5       92000 ops/s
      2  global bigint 5       34200 ops/s
      3  123 ()               160000 ops/s
      4  123 undef             82800 ops/s (empty: 36300, both: 25200)
      5  123 scalar 5          14000 ops/s (empty: 36500, both: 10100)
      6  123 bigint 5           8590 ops/s (empty: 213000, both: 8260)
      7  12345 scalar 2         8440 ops/s (empty: 36100, both: 6840)
      8  12345 bigint 2         7050 ops/s (empty: 36300, both: 5900)
 Average:                      50900 ops/s
 Benchmarking group 2 ('precision'):
      9  global scalar 5      105000 ops/s
     10  global bigint 5       39100 ops/s
     11  123 ()               161000 ops/s
     12  123 undef             89300 ops/s (empty: 36400, both: 25800)
     13  123 scalar -5         28000 ops/s (empty: 36400, both: 15800)
     14  123 bigint -5         17200 ops/s (empty: 36500, both: 11700)
     15  12345 scalar -2       28000 ops/s (empty: 36400, both: 15800)
     16  12345 bigint -2       17500 ops/s (empty: 36200, both: 11800)
     17  123 scalar 5           6170 ops/s (empty: 36400, both: 5270)
     18  123 bigint 5           5420 ops/s (empty: 36500, both: 4720)
     19  12345 scalar 2         6380 ops/s (empty: 36200, both: 5420)
     20  12345 bigint 2         5520 ops/s (empty: 36100, both: 4790)
 Average:                      42300 ops/s

Tue Dec  3 21:11:08 2002 Numbers are absolute ops/s, scaled by factor 1.

                  |   v1.64   v1.65
                  |   fixed        
 -----------------+-----------------
  global scalar 5 |  104000   92000
  global bigint 5 |    3900   34200
  123 ()          |  158000  160000
  123 undef       |  112000   82800
  123 scalar 5    |   14300   14000
  123 bigint 5    |    2130    8590
  12345 scalar 2  |    8660    8440
  12345 bigint 2  |    2030    7050
 accuracy:        |   50700   50900
 .................|.................
  global scalar 5 |  106000  105000
  global bigint 5 |  103000   39100
  123 ()          |  159000  161000
  123 undef       |  115000   89300
  123 scalar -5   |   27600   28000
  123 bigint -5   |    5070   17200
  12345 scalar -2 |   27300   28000
  12345 bigint -2 |    5110   17500
  123 scalar 5    |    6220    6170
  123 bigint 5    |    1310    5420
  12345 scalar 2  |    6320    6380
  12345 bigint 2  |    1250    5520
 precision:       |   46900   42300
 .................|.................

Tue Dec  3 21:11:09 2002 All done. Enjoy!

###############################################################################
# BigBenchmark data file.
#
# Contains all the groups and ops you want to benchmark.
#
# Format is as follows:
#
# For defining groups:
# group=groupid#groupname#groupdescription
# The ops follow the group defintion and go like this:
# opid#opname#startupcode#emptycode#benchmarkcode
#
# The opid is to sort the ops in one group, they will be done numerically
# sorted. Same goes for group id's, lowest id will be benchmarked first.
# You can leave group and op id's empty (set to 0), then they will be
# filled-in automatically.
#
# The startup code is done before running the benchmark, so set any variables
# you need there. The empty code is benchmarked and then subtracted from the
# benchmark's code timing.
###############################################################################

# BigInt/BigFloat:
# You should use $c->new(); instead of Math::BigInt->new() etc, so that
# the benchmarks are independed of the actual class used.

# Actual definitions:

group=accuracy#0#BigInt accuracy()
0#global scalar 5###$c->accuracy(5);
0#global bigint 5#$x=$c->new(5);##$c->accuracy($x);
0#123 ()#$c->accuracy(undef);$x=$c->new('123');##$x->accuracy();
0#123 undef#$x=$c->new('123');#$x->copy();#$x->copy()->accuracy(undef);
0#123 scalar 5#$x=$c->new('123');#$x->copy();#$x->copy()->accuracy(5);
0#123 bigint 5#$x=$c->new('123');$y=$c->new(5)#$c->copy();#$x->copy()->accuracy(
$y);
0#12345 scalar 2#$x=$c->new('12345');#$x->copy();#$x->copy()->accuracy(2);
0#12345 bigint 2#$x=$c->new('12345');$y=$c->new(2)#$x->copy();#$x->copy()->accur
acy($y);

group=precision#0#BigInt precision()
0#global scalar 5###$c->precision(5);
0#global bigint 5#$x=$c->new(5);##$c->precision($x);
0#123 ()#$x=$c->new('123');##$x->precision();
0#123 undef#$c->precision(undef);$x=$c->new('123');#$x->copy();#$x->copy()->prec
ision(undef);
0#123 scalar -5#$x=$c->new('123');#$x->copy();#$x->copy()->precision(-5);
0#123 bigint -5#$x=$c->new('123');$y=$c->new(-5)#$x->copy()#$x->copy()->precisio
n($y);
0#12345 scalar -2#$x=$c->new('12345');#$x->copy();#$x->copy()->precision(-2);
0#12345 bigint -2#$x=$c->new('12345');$y=$c->new(-2)#$x->copy();#$x->copy()->pre
cision($y);
0#123 scalar 5#$x=$c->new('123');#$x->copy();#$x->copy()->precision(5);
0#123 bigint 5#$x=$c->new('123');$y=$c->new(5)#$x->copy();#$x->copy()->precision
($y);
0#12345 scalar 2#$x=$c->new('12345');#$x->copy();#$x->copy()->precision(2);
0#12345 bigint 2#$x=$c->new('12345');$y=$c->new(2)#$x->copy();#$x->copy()->preci
sion($y);


[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]