[libmath-prime-util-perl] 03/05: Add MemFree object for better memory control

Partha P. Mukherjee ppm-guest at moszumanska.debian.org
Thu May 21 18:44:12 UTC 2015


This is an automated email from the git hooks/post-receive script.

ppm-guest pushed a commit to annotated tag v0.01
in repository libmath-prime-util-perl.

commit 173374eaaf4cb26d7f1a38ac164870fdc8b01fb0
Author: Dana Jacobsen <dana at acm.org>
Date:   Sun Jun 3 21:06:27 2012 -0600

    Add MemFree object for better memory control
---
 lib/Math/Prime/Util.pm | 77 +++++++++++++++++++++++++++++++++++---------------
 t/03-init.t            | 39 +++++++++++++++++++++++--
 2 files changed, 91 insertions(+), 25 deletions(-)

diff --git a/lib/Math/Prime/Util.pm b/lib/Math/Prime/Util.pm
index 5315dbc..f71ce1f 100644
--- a/lib/Math/Prime/Util.pm
+++ b/lib/Math/Prime/Util.pm
@@ -88,6 +88,23 @@ sub primes {
   return $sref;
 }
 
+# We use this object to let them control when memory is freed.
+package Math::Prime::Util::MemFree;
+use Carp qw/croak confess/;
+my $memfree_instances = 0;
+sub new {
+  my $self = bless {}, shift;
+  $memfree_instances++;
+  return $self;
+}
+sub DESTROY {
+  my $self = shift;
+  confess "instances count mismatch" unless $memfree_instances > 0;
+  Math::Prime::Util::prime_free if --$memfree_instances == 0;
+}
+package Math::Prime::Util;
+
+
 
 1;
 
@@ -137,26 +154,6 @@ including Math::Prime::XS, Math::Prime::FastSieve, and Math::Factor::XS.
 
 =head1 FUNCTIONS
 
-=head2 prime_precalc
-
-  prime_precalc( 1_000_000_000 );
-
-Let the module prepare for fast operation up to a specific number.  It is not
-necessary to call this, but it gives you more control over when memory is
-allocated and gives faster results for multiple calls in some cases.  In the
-current implementation this will calculate a sieve for all numbers up to the
-specified number.
-
-
-=head2 prime_free
-
-  prime_free;
-
-Frees any extra memory the module may have allocated.  Like with
-C<prime_precalc>, it is not necessary to call this, but if you're done
-making calls, or want things cleanup up, you can use this.
-
-
 =head2 is_prime
 
 Returns true if the number is prime, false if not.
@@ -290,11 +287,45 @@ generate any primes.  Uses the Cipolla 1902 approximation with two
 polynomials, plus a correction term for small values to reduce the error.
 
 
+=head1 UTILITY FUNCTIONS
+
+=head2 prime_precalc
+
+  prime_precalc( 1_000_000_000 );
+
+Let the module prepare for fast operation up to a specific number.  It is not
+necessary to call this, but it gives you more control over when memory is
+allocated and gives faster results for multiple calls in some cases.  In the
+current implementation this will calculate a sieve for all numbers up to the
+specified number.
+
+
+=head2 prime_free
+
+  prime_free;
+
+Frees any extra memory the module may have allocated.  Like with
+C<prime_precalc>, it is not necessary to call this, but if you're done
+making calls, or want things cleanup up, you can use this.  The object method
+might be a better choice for complicated uses.
+
+=head2 Math::Prime::Util::MemFree->new
+
+  my $mf = Math::Prime::Util::MemFree->new
+  # perform operations.  When $mf goes out of scope, memory will be recovered.
+
+This is a more robust way of making sure any cached memory is freed, as it
+will be handled by the last C<MemFree> object leaving scope.  This means if
+your routines were inside an eval that died, things will still get cleaned up.
+If you call another function that uses a MemFree object, the cache will stay
+in place because you still have an object.
+
+
 =head1 LIMITATIONS
 
-Some of the functions have not yet transitioned to using a segmented sieve,
-so will use too much memory to be practical when called with very large
-numbers (C<10^11> and up).
+The functions C<prime_count> and C<nth_prime> have not yet transitioned to
+using a segmented sieve, so will use too much memory to be practical when
+called with very large numbers (C<10^11> and up).
 
 I have not completed testing all the functions near the word size limit
 (e.g. C<2^32> for 32-bit machines).  Please report any problems you find.
diff --git a/t/03-init.t b/t/03-init.t
index aad681b..17690db 100644
--- a/t/03-init.t
+++ b/t/03-init.t
@@ -3,9 +3,11 @@ use strict;
 use warnings;
 use Math::Prime::Util qw/prime_precalc prime_free/;
 
-use Test::More  tests => 3;
+use Test::More  tests => 3 + 3 + 3 + 6;
 
 
+my $bigsize = 10_000_000;
+
 # How do we test these?  Use some private functions and assume things about
 # internal behavior.  Not the best idea.
 
@@ -13,10 +15,43 @@ can_ok( 'Math::Prime::Util', '_get_prime_cache_size' );
 
 my $init_size = Math::Prime::Util::_get_prime_cache_size;
 
-prime_precalc(10_000_000);
+prime_precalc($bigsize);
 
 cmp_ok( Math::Prime::Util::_get_prime_cache_size, '>', $init_size, "Internal space grew after large precalc" );
 
 prime_free;
 
 is( Math::Prime::Util::_get_prime_cache_size, $init_size, "Internal space went back to original size after free" );
+
+
+# Now do the object way.
+{
+  my $mf = new_ok( 'Math::Prime::Util::MemFree');
+  prime_precalc($bigsize);
+  cmp_ok( Math::Prime::Util::_get_prime_cache_size, '>', $init_size, "Internal space grew after large precalc" );
+}
+is( Math::Prime::Util::_get_prime_cache_size, $init_size, "Memory released after MemFree object goes out of scope");
+
+# Wrap multiple calls, make sure we wait until the last one is done.
+{
+  my $mf = Math::Prime::Util::MemFree->new;
+  prime_precalc($bigsize);
+  cmp_ok( Math::Prime::Util::_get_prime_cache_size, '>', $init_size, "Internal space grew after large precalc" );
+  {
+    my $mf2 = Math::Prime::Util::MemFree->new;
+    prime_precalc( 2 * $bigsize );
+  }
+  cmp_ok( Math::Prime::Util::_get_prime_cache_size, '>', $init_size, "Memory not freed yet because a MemFree object still live." );
+}
+is( Math::Prime::Util::_get_prime_cache_size, $init_size, "Memory released after last MemFree object goes out of scope");
+
+# Show how an eval death can leak
+eval { prime_precalc($bigsize); cmp_ok( Math::Prime::Util::_get_prime_cache_size, '>', $init_size, "Internal space grew after large precalc" ); prime_free; };
+is( Math::Prime::Util::_get_prime_cache_size, $init_size, "Memory freed after eval");
+
+eval { prime_precalc($bigsize); cmp_ok( Math::Prime::Util::_get_prime_cache_size, '>', $init_size, "Internal space grew after large precalc" ); die; prime_free; };
+isnt( Math::Prime::Util::_get_prime_cache_size, $init_size, "Memory normally not freed after eval die");
+prime_free;
+
+eval { my $mf = Math::Prime::Util::MemFree->new; prime_precalc($bigsize); cmp_ok( Math::Prime::Util::_get_prime_cache_size, '>', $init_size, "Internal space grew after large precalc" ); die; prime_free; };
+is( Math::Prime::Util::_get_prime_cache_size, $init_size, "Memory is not freed after eval die using object scoper");

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libmath-prime-util-perl.git



More information about the Pkg-perl-cvs-commits mailing list