如何从内存

时间:2016-11-13 14:04:01

标签: perl memory-management

我在编写的perl脚本的内存使用方面遇到了一些问题(下面的代码)。该脚本启动一些变量,用数据填充它们,然后再次取消定义它们。但是,删除所有内容后脚本的内存使用量仍然很高,不包含任何数据。

根据ps脚本在前39秒内使用1.027 Mb内存(RSS)(所以在foreach循环之前的所有内容)。然后,内存使用量开始上升,最终在204.391 Mb和172.410 Mb之间波动。但是,即使在脚本的最后10秒内(应该删除所有数据),内存使用量也不会低于172.410 Mb。

有没有办法永久删除perl中的变量及其中的所有数据(为了减少脚本的内存使用量)?如果是这样,我该怎么做?

use strict;
use warnings;

sleep(30);

my $ELEMENTS = 1_000_000;
my $MAX_ELEMENT = 1_000_000_000;
my $if_condition = 1;

sleep(5);

my %hash = (1 => {}, 2 => {}, 3 => {}, 4 => {});

foreach my $key (keys %hash){
    if( $if_condition ){
        my $arrref1 = [ (rand($MAX_ELEMENT)) x $ELEMENTS ];
        my $arrref2 = [ (rand($MAX_ELEMENT)) x $ELEMENTS ];
        my $arrref3 = [ (rand($MAX_ELEMENT)) x $ELEMENTS ];

        sleep(2);

        if(!defined($hash{$key}->{'amplification'})){
            $hash{$key}->{'amplification'} = [];
        }

        push(@{$hash{$key}->{'amplification'}},@{$arrref1});
        undef($arrref1);
        push(@{$hash{$key}->{'amplification'}},@{$arrref2});
        undef($arrref2);
        push(@{$hash{$key}->{'amplification'}},@{$arrref3});
        undef($arrref3);


        sleep(3);

        delete($hash{$key});

        sleep(5);
    }
}

sleep(10);

2 个答案:

答案 0 :(得分:6)

Perl常见问题解答3 - How can I free an array or hash so my program shrinks?

  

你通常不能。分配给词汇的内存(即my()变量)   即使超出范围也不能回收或重复使用。它是   保留以防变量返回范围。分配内存   通过使用可以重用(在程序中)全局变量   undef()和/或delete()。

     

在大多数操作系统上,已分配内存   一个程序永远不会返回到系统。这就是原因   长期运行的程序有时会重新执行。一些操作   系统(特别是使用mmap(2)分配大块的系统   内存)可以回收不再使用的内存,但就此而言   系统,perl必须配置和编译才能使用OS的malloc,   不是perl的。

     

通常,内存分配和解除分配不是   你可以或应该在Perl中担心的事情。

     

另见   "如何让我的Perl程序占用更少的内存?"

答案 1 :(得分:0)

通常,perl不会将内存释放回系统。它保留自己的内存池,以防其他目的需要它。这种情况发生很多,因为词法数据经常在循环中使用,例如,您的$arrref1变量引用了一个百万元素数组。如果这些数组的内存返回到系统并且每次循环重新分配,那么将会有巨大的速度损失

正如我所写,170MB并不是很多,但您可以通过删除大型临时数组并将列表直接添加到哈希元素来减少占用空间。就目前而言,你不必要地保留每个数组的两个副本

看起来像这样

use strict;
use warnings 'all';

sleep 30;

use constant ELEMENTS    => 1_000_000;
use constant MAX_ELEMENT => 1_000_000_000;

my $if_condition = 1;

sleep 5;

my %hash = ( 1 => {}, 2 => {}, 3 => {}, 4 => {} );

foreach my $key ( keys %hash ) {

    next unless $if_condition;


    sleep 2;

    push @{ $hash{$key}{amplification} }, (rand MAX_ELEMENT) x ELEMENTS;
    push @{ $hash{$key}{amplification} }, (rand MAX_ELEMENT) x ELEMENTS;
    push @{ $hash{$key}{amplification} }, (rand MAX_ELEMENT) x ELEMENTS;


    sleep 3;

    delete $hash{$key};

    sleep 5;
}

sleep 10;