删除元素时,Perl中的哈希值会缩小吗?

时间:2008-09-24 23:03:20

标签: performance perl

删除元素时,Perl中的哈希值会缩小吗?

更具体地说,我有一个我继承的perl程序,它会解析一个巨大的文件(1 GB)并加载哈希哈希值。它会对另一个文件执行相同的操作,然后对不同的元素进行比较。在此过程中内存消耗量很大,即使我添加了删除哈希元素,但是使用它们的内存消耗似乎没有受到影响。

脚本非常慢,而且这样的内存耗尽。我知道它没有很好的设计,但有关哈希内存使用的任何想法?

6 个答案:

答案 0 :(得分:11)

您可能需要查看DBM::Deep之类的内容。它确实提到了迈克尔提到的那些东西,所以你不必考虑它。一切都存储在磁盘而不是内存中。它只是缺少一个更高级的数据库服务器。

此外,如果您想追踪性能瓶颈,请查看Devel::NYTProf,这是New York Times 中出现的Perl概要分析中的新热点。

答案 1 :(得分:7)

通常,Perl无法将内存返回给操作系统。但是,它可以在内部重用内存,这可以减少程序所需的内存量。

见perlfaq3:How can I free an array or hash so my program shrinks?

如果哈希使用的内存过多(即>物理内存),您可以tie将它们放到磁盘上的文件中。这将大大减少您的内存使用量,但要注意访问磁盘上的结构比访问内存中的结构要慢得多。 (磁盘颠簸也是如此。)

答案 2 :(得分:5)

如果你的哈希是真正巨大的,一个更好的策略是可能使用磁盘上的哈希,并让操作系统担心进出内存。我特别喜欢Berkeley DB在磁盘上存储大哈希,而Perl BerkeleyDB模块提供了一个功能齐全的界面,包括一个绑定的API。

DBM::Deep也可以用作插入式哈希替换,但依赖于自己的格式。如果您的结构需要被其他(非Perl)系统读取,这可能会很痛苦。

答案 3 :(得分:5)

关于具体问题:不,删除哈希键不会减少程序的内存消耗。

关于更一般的情况:绝大多数程序和语言将继续保留他们以前使用过的内存,但目前尚未使用。这是因为请求操作系统分配内存是一个相对较慢的操作,所以他们保留它以防以后再次需要。

因此,如果你想改善这种情况,你需要减少程序所需的峰值内存量,无论是通过修改你的算法来不需要一次访问那么多的数据,通过使用on-磁盘存储(例如前面提到的DBM :: Deep),或者将不需要的变量中的空间释放回perl(让它们超出范围或将它们设置为 undef ),以便可以重复使用它。

答案 4 :(得分:4)

如果第二个文件中的输入只需要一次(因为它们被读取),你可能会将内存使用量减少一半。

根据您的算法,您甚至可以只打开两个文件句柄,并在内存中保留一小部分未使用的值。一个例子是对已排序数据进行合并或比较 - 您只需要保留每个文件中的当前行并在进行时将其进行比较,直到cmp更改为止。

另一种方法可能是进行多次传递,特别是如果您的计算机中有一个或多个空闲的核心。打开读取管道并让子流程以可管理的预先组织的块为您提供数据。

对于更通用的算法,您只能通过交换磁盘速度来避免支付内存大小。

在大多数情况下,将每个数据源加载到内存中只会在开发时间内获胜 - 然后在N变大时以足迹和/或速度为其付费。

答案 5 :(得分:4)

解决方法:派生子进程分配所有内存。当它完成它的事情时,让它传回一些聚合信息;当分叉进程终止时,它的内存将随之而来。有点痛,但适用于某些情况。例如,如果您正在处理许多文件,每个文件一次只有一个,只有少数文件很大,并且需要保留很少的中间状态,这会有所帮助。