如何在Perl中查找哈希所占用的物​​理内存量?

时间:2020-03-06 14:28:22  来源:igfitidea点击:

我有一个Perl脚本,其中使用哈希表维护非常简单的缓存。我想清除散列占用的字节数超过n个字节的情况,以避免Perl(32位)内存不足并崩溃。

我可以检查键值对的数量:

if (scalar keys %cache > $maxSize)
 {
 %cache = ();
 }

但是可以检查散列占用的实际内存吗?

解决方案

我们在寻找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来确定所使用的内存,但是通常不能将返回内存提供给OS。听起来我们只是在尝试清除和重用,这应该可以正常工作。

如果缓存用于功能,请考虑使用Memoize模块,而不要自己维护缓存。它支持缓存过期(通过Memoize :: Expire),因此我们可以限制缓存的大小而不会完全破坏它。

我们可以安装Devel :: Size来查找Perl中任何构造占用的内存。但是请注意,它将占用大量的中间存储器,因此我不会将其用于大型数据结构。如果我们认为我们可能快要用尽内存,那么我当然不会这样做。

顺便说一句,CPAN上有很多不错的模块可以在内存中进行缓存,否则就不行了。我建议不要使用其中之一,而不是自己动手。例如,尝试使用Tie :: Cache :: LRU进行内存缓存,该缓存最多只能存储指定数量的键。

Devel :: Size是我们问题的答案。 (请注意,Devel :: Size在处理大型数据结构时会临时分配大量内存,因此,它并不是非常适合此目的。)

但是,Cache :: SizeAwareMemoryCache和Tie :: Cache已经实现了我们要寻找的内容(具有一些不同的接口),并且可以避免重新发明轮子。

Memoize是一个模块,可简化从函数中缓存返回值的过程。它没有实现基于大小的缓存限制,但是应该可以将Tie :: Cache用作Memoize的后端。

高速缓存存储器

use Cache::Memory;

my $cache = Cache::Memory->new(
  namespace => 'MyNamespace',
  default_expires => '600 sec'
);

my $size  = $cache->size()
my $limit = $cache->size_limit();

如果我们担心管理Perl正在使用的内存量,则可能应该考虑使用另一种方法。为什么一次需要那么多的RAM?我们应该使用某种持久性系统吗?

正如其他人所说,缓存不是我们需要重新发明的轮子,CPAN上有很多简单的缓存解决方案,它们会为我们做得很好。

Cache :: SizeAwareMemoryCache会被告知我们要使用的最大大小,然后可以将其保留下来以照顾缓存。