如何在Perl中查找哈希所占用的物理内存量?
我有一个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会被告知我们要使用的最大大小,然后可以将其保留下来以照顾缓存。