Memoize::Expire::ByInstance

A Memoize plugin which provides per-class-instance expiration of memoized data
Download

Memoize::Expire::ByInstance Ranking & Summary

Advertisement

  • Rating:
  • License:
  • Perl Artistic License
  • Price:
  • FREE
  • Publisher Name:
  • Jamie Beverly
  • Publisher web site:
  • http://search.cpan.org/~jbeverly/

Memoize::Expire::ByInstance Tags


Memoize::Expire::ByInstance Description

Memoize::Expire::ByInstance is a Perl module for Memoize which supports memoization of class-methods and allows you to set their maximums for expiration on a per-instance bases.Memoize works by caching the returend value of a function invocation in a hash of ($arguments => $returned_value). On subsequent calls to that function, if the arguments are identical, the $returned_value is returned from the hash instead of from calling the function again.Because you often only want to cache for a brief period of time, of a limited number of uses, there exists a module called Memoize::Expire. Memoize and Memoize::Expire typically do what you want 90% of the time.However, in the case of class-methods, you frequently have do extra work to obtain the benefits of memoization. However, this still proves insufficient for cases where you would like to allow your object to provide customizable expiration/timeout values on a per-instance bases.If you tie a hash to Memoize::Expire for each instance, you lose the benefit of class-method memoization, and if you tie a hash to Memoize::Expire for the entire class, you are unable to have per-instance timeout/expirations.When you want/need BOTH class-method memoization AND per-instance timeout/expiration limits, you will need to use Memoize::Expire::ByInstance (this module.) ### OPTION A: ### All instances expire after 30 seconds, or 100 uses. It is not customizable. { package Foo; use Memoize; use Memoize::Expire; sub normy { shift; return( join(chr(0x1C), @_) ) }; tie my %foo => 'Memoize::Expire', LIFETIME => 30, NUM_USES => 100; memoize('my_class_method', SCALAR_CACHE => , LIST_CACHE => , NORMALIZER => 'normy'); ## This is a class method, not an instance method. It does NOT use any per-instance data. sub my_class_method { my ($self, $val1, $val2) = @_; return( something($val1) + something_else($val2) ); } sub new { my ($proto, %args) = @_; my $class = ref($proto) || $proto; my $self = bless(\%args, $class); return $self; } } ### OPTION B: ### All instances have a unique hash, regardless of NORMALIZER trickery or scoping fun. { package Foo; use Memoize; use Memoize::Expire; ## This is a class method, not an instance method. It does NOT use any per-instance data. sub my_class_method { my ($self, $val1, $val2) = @_; return( something($val1) + something_else($val2) ); } sub new { my ($proto, %args) = @_; my $class = ref($proto) || $proto; my $self = bless(\%args, $class); ## unique hash, re-memoized, no joy ## If you use %Foo::foo instead, you'll just nuke the contents of it, and reset the expiration ## every time the class is re-instanced. tie my %Foo => 'Memoize::Expire', LIFETIME => $self->{lifetime}, NUM_USES => $self->{num_uses}; memoize('my_class_method', SCALAR_CACHE => , LIST_CACHE => ); return $self; } }SYNOPSIS ### Specify a per-instance maximum cache duration, while only ever calling the underlying function when actually ### needed; i.e. When we've not seen those arguments before, or whenever a method is called upon an instance ### who's lifetime or num_uses has been exceeded. { package Foo; use Memoize; use Memoize::Expire::ByInstance; tie my %foo => 'Memoize::Expire::ByInstance', LIFETIME => 30, NUM_USES => 100, AUTO_DESTROY => 1; memoize('my_class_method', SCALAR_CACHE => , LIST_CACHE => ); ## This is a class method, not an instance method. It does NOT use any per-instance data. sub my_class_method { my ($self, $val1, $val2) = @_; return( something($val1) + something_else($val2) ); } sub new { my ($proto, %args) = @_; my $class = ref($proto) || $proto; my $self = bless(\%args, $class); ### Register this specific instances idea of "too old" (tied %foo)->register("$self", lifetime => $args{lifetime}, num_uses => $args{num_uses}); return $self; } } my $needs_fresh_data = Foo->new( lifetime => 1, num_uses => 10 ); my $can_use_old_data = Foo->new( lifetime => 300, num_uses => 10000 ); my $will_rely_on_default_ages = Foo->new(); # Calls on this instance will always get data less than 1 second old, or less than 10 uses old $needs_fresh_data->my_class_method( 1, 2 ); # Calls on this instance will always get data less than 300 second old, or less than 10000 uses old # Since we just called my_class_method on $needs_fresh_data, it will not be invoked this time. $can_use_old_data->my_class_method( 1, 2 ); # Calls on this instance will always get data less than 30 second old, or less than 100 uses old (the defaults specified when first tied) # Since we just called my_class_method on $needs_fresh_data, it will not be invoked this time. $will_rely_on_default_ages->my_class_method( 1, 2 ); sleep(2); # Still good, my_class_method is not called. $can_use_old_data->my_class_method( 1, 2 ); # Still good, my_class_method is not called $will_rely_on_default_ages->my_class_method( 1, 2 ); # 2 seconds > 1 second; will invoke my_class_method again. $needs_fresh_data->my_class_method( 1, 2 );Note that ALL calls to "my_class_method" regardless of which instance they were called upon, are Memoized as though they're only arguments had been (1, 2). Calls on any instance will bypass the expensive method invocation as long as that method has been called with the same (non-instance) arguments recently enough.Product's homepage


Memoize::Expire::ByInstance Related Software