Attribute-Cached
view release on metacpan or search on metacpan
lib/Attribute/Cached.pm view on Meta::CPAN
my $sub = encache($pkg, $name, $code, %config);
my $subname = "${pkg}::${name}";
warn "Installing into $subname" if DEBUG;
no strict 'refs';
no warnings 'redefine';
*{$subname} = $sub;
}
sub encache {
my ($pkg, $name, $code, %config) = @_;
return unless my $ct
= $config{time} || $pkg->can('getCacheTime');
warn "code is $name, $code" if DEBUG;
my $getCache = $config{cache} || $pkg->can('getCache');
my $getCacheKey = $config{key}
|| $pkg->can('getCacheKey')
|| \&getCacheKeyDefault;
my $transform = $config{transform} || $pkg->can('cacheTransform');
my $sub = sub {
# give the anonymous sub a name
# (alternatively, use Sub::Named, as suggested by Ash)
local *__ANON__ = "Cached($name)";
my $cache = literalOrCall($getCache, @_);
my $key = $pkg->$getCacheKey( $name, @_ );
my $result = $cache->get( $key );
if ($result) {
warn "Cache($name) hit for $key => $result" if DEBUG;
} else {
warn "Cache($name) miss for $key" if DEBUG;
$result = $code->(@_);
# we could have been passed a subroutine!
my $cachetime = literalOrCall($ct, $pkg, $name, @_);
warn "Cache($name) Setting $key => $result ($cachetime)" if DEBUG;
$cache->set( $key, $result, $cachetime );
}
return $result unless $transform;
return $transform->($result, @_);
};
return $sub;
}
sub getCacheKeyDefault {
return join ';' => @_;
}
sub literalOrCall {
my $what = shift;
return $what unless ref $what eq 'CODE';
return $what->(@_);
}
1;
=head1 PERFORMANCE
Automatically wrapping the caching logic requires a slightly generic approach
which may not be optimal. The bundled C<attr_bench.pl> program tries to
quantify this. In a sample run of 1,000,000 iterations, it can be seen that
the additional work requires approximately 10 millionths of a second per
iteration. This is likely to be fast enough for most requirements.
Using the Attribute::Handling (instead of manually using the C<encache>
subroutine which does the actual work) appears to be a tiny fraction of the
total overhead (1 millionth of a second per iteration).
(Benchmark results on my machine, please give me a shout if you get wildly
different results).
=head1 SEE ALSO
The attribute code is "inspired" by L<Attribute::Memoize>, and uses the very
funky L<Attribute::Handlers>. This latter seems to be full of very tasty
crack, but is also much nicer than doing the attribute parsing ourselves.
You'll need a caching module like L<Cache::Cache> or L<Cache::Memcached>.
The wrapping might be done better with L<Hook::LexWrap>
=head1 STATUS and BUGS
This is version 0.01, in alpha. The interface is likely to
change, as indicated in several places in comments in the above
POD. Please get in touch if you have suggestions or concerns
about the public API.
Please report via RT on cpan, or to L<mailto:osfameron@cpan.org>.
Or grab osfameron on IRC, for example on C<irc.perl.org #london.pm>
=head1 AUTHOR and LICENSE
By osfameron, for Thermeon Ltd.
(C)2007 Thermeon Europe
This program is free software, you can redistribute it and/or modify it under
the same terms as Perl itself.
=cut
( run in 0.558 second using v1.01-cache-2.11-cpan-96521ef73a4 )