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

时间:2020-03-06 14:41:38  来源:igfitidea点击:

删除元素时,Perl中的哈希值是否缩小?

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

该脚本非常慢,而且占用了大量内存。我知道它的设计不是很好,但是有关哈希内存使用的任何想法吗?

解决方案

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

请参阅perlfaq3:如何释放数组或者哈希以缩小程序?

如果哈希使用的内存过多(即>物理内存),则可以将它们``绑定''到磁盘上的文件中。这将大大减少内存使用量,但是要警告,访问磁盘上的结构比访问内存中的结构要慢得多。 (磁盘跳动也是如此。)

我们可能想签出类似DBM :: Deep的东西。它确实完成了Michael提到的相关内容,因此我们不必考虑它。一切都存储在磁盘上,而不是存储在内存中。它只需要一个更高级的数据库服务器。

另外,如果我们想查找性能瓶颈,请查看Devel :: NYTProf,这是《纽约时报》提出的Perl分析中的新热点。

如果哈希值确实是巨大的,则更好的策略是使用磁盘上的哈希值,并使OS担心将数据放入内存或者从内存中取出。我特别喜欢Berkeley DB在磁盘上存储大哈希,并且Perl BerkeleyDB模块提供了功能齐全的接口,包括绑定的API。

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

如果第二个文件中的输入仅需要一次(读取时),则可能会将内存使用量减少一半。

根据算法,我们甚至可以只打开两个文件句柄,并在内存中保留一些尚未使用的值。一个例子是对已排序数据进行合并或者比较-我们只需要保留每个文件中的当前行,并在进行时将它们相互比较,就可以跳过直到cmp更改为止。

另一种方法可能是多次通过,尤其是在计算机中有一个或者多个其他空闲内核的情况下。打开读取管道并让子流程以可管理的预组织块的形式向我们提供数据。

对于更通用的算法,我们只能通过以磁盘速度为代价来交换内存大小,从而避免为此付出代价。

在大多数情况下,将每个数据源加载到内存中只会赢得开发时间-然后,当N变大时,我们需要在占用空间和/或者速度上付出代价。

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

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

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

解决方法:派生一个分配所有内存的子进程。完成工作后,让它返回一些汇总信息;当分叉的进程死亡时,它的内存将随之消失。有点痛苦,但在某些情况下有效。例如,如果我们正在处理许多文件,一次处理一个文件,只有几个文件很大,并且几乎不需要保留任何中间状态,那么这将对我们有所帮助。