[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