我有一个 Perl 脚本,我在其中使用哈希表维护一个非常简单的缓存。一旦它占用超过 n 个字节,我想清除哈希,以避免 Perl(32 位)内存不足和崩溃。
我可以检查键值对的数量:
if (scalar keys %cache > $maxSize)
{
%cache = ();
}
但是是否可以检查散列占用的实际内存?
Devel::Size是您问题的答案。(请注意,Devel::Size 在处理大型数据结构时会临时分配大量内存,因此它不太适合此目的。)
但是,Cache::SizeAwareMemoryCache和Tie::Cache已经实现了您正在寻找的东西(使用有些不同的接口),并且可以避免您重新发明轮子。
Memoize是一个模块,可以轻松缓存函数的返回值。它没有实现基于大小的缓存限制,但应该可以使用 Tie::Cache 作为 Memoize 的后端。
您正在寻找Devel::Size
Devel::Size - 用于查找 Perl 变量的内存使用情况的 Perl 扩展
use Devel::Size qw(size total_size);
my $size = size("A string");
my @foo = (1, 2, 3, 4, 5);
my $other_size = size(\@foo);
my $foo = {a => [1, 2, 3],
b => {a => [1, 3, 4]}
};
my $total_size = total_size($foo);
您可以安装Devel::Size以找出 Perl 中任何构造所占用的内存。但是请注意,它会占用大量中间内存,因此我不会将它用于大型数据结构。如果您认为您可能即将耗尽内存,我当然不会这样做。
顺便说一句,CPAN 上有许多很好的模块可以在内存中进行缓存等。我建议不要自己动手,而是使用其中之一。例如,尝试Tie::Cache::LRU用于内存缓存,该缓存只能达到指定数量的键。
您可以使用Devel::Size来确定使用的内存,但通常不能将返回内存提供给操作系统。不过,听起来您只是想清除和重用,这应该可以正常工作。
如果缓存是用于函数的,请考虑使用Memoize模块,而不是自己维护缓存。它支持缓存过期(通过 Memoize::Expire),因此您可以限制缓存的大小而不会完全破坏它。
use Cache::Memory;
my $cache = Cache::Memory->new(
namespace => 'MyNamespace',
default_expires => '600 sec'
);
my $size = $cache->size()
my $limit = $cache->size_limit();
如果您担心管理 Perl 正在使用的内存量,您可能应该考虑另一种方法。为什么你一次需要这么多内存?你应该使用某种持久性系统吗?
正如其他人所说,缓存不是您需要重新发明的轮子,CPAN 上有很多简单的缓存解决方案可以很好地为您完成这项工作。
Cache::SizeAwareMemoryCache可以被告知您希望它使用的最大大小,然后您可以让它为您处理缓存。