简体   繁体   English

如何从内存中删除Perl对象

[英]How can I remove perl object from memory

I'm having some issues with the memory usage of a perl script I wrote (code below). 我编写的Perl脚本的内存使用存在一些问题(下面的代码)。 The script initiates some variables, fills them with data, and then undefines them again. 该脚本会初始化一些变量,并用数据填充它们,然后再次取消定义它们。 However, the memory usage of the script after deleting everything is still way to high to contain no data. 但是,删除所有内容后脚本的内存使用率仍然很高,无法包含任何数据。

Accoring to ps the script uses 1.027 Mb memory (RSS) during the first 39 seconds (so everything before the foreach loop). 根据ps ,脚本在前39秒内使用1.027 Mb内存(RSS)(因此,foreach循环之前的所有内容)。 Then, memory usage starts rising and ends up fluctuating between 204.391 Mb and 172.410 Mb. 然后,内存使用率开始上升,最终在204.391 Mb和172.410 Mb之间波动。 However, even in the last 10 seconds of the script (where all data is supposed to be removed), memory usage never goes below 172.410 Mb. 但是,即使在脚本的最后10秒(应该删除所有数据)中,内存使用量也永远不会低于172.410 Mb。

Is there a way to permanently delete a variable and all data in it in perl (in order to reduce the memory usage of the script)? 有没有一种方法可以永久删除perl中的变量及其中的所有数据(以减少脚本的内存使用量)? If so, how should I do it? 如果是这样,我该怎么办?

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);

Perl FAQ 3 - How can I free an array or hash so my program shrinks? Perl常见问题3- 如何释放数组或哈希以缩小程序?

You usually can't. 你通常不能。 Memory allocated to lexicals (ie my() variables) cannot be reclaimed or reused even if they go out of scope. 分配给词法的内存(即my()变量)即使超出范围也无法回收或重新使用。 It is reserved in case the variables come back into scope. 如果变量返回范围,则保留该字段。 Memory allocated to global variables can be reused (within your program) by using undef() and/or delete(). 通过使用undef()和/或delete(),可以重新分配给全局变量的内存(在程序内)。

On most operating systems, memory allocated to a program can never be returned to the system. 在大多数操作系统上,分配给程序的内存永远不会返回给系统。 That's why long-running programs sometimes re- exec themselves. 因此,长时间运行的程序有时会自行执行。 Some operating systems (notably, systems that use mmap(2) for allocating large chunks of memory) can reclaim memory that is no longer used, but on such systems, perl must be configured and compiled to use the OS's malloc, not perl's. 某些操作系统(尤其是使用mmap(2)分配大块内存的系统)可以回收不再使用的内存,但是在此类系统上,必须将perl配置和编译为使用OS的malloc,而不是perl。

In general, memory allocation and de-allocation isn't something you can or should be worrying about much in Perl. 通常,内存分配和取消分配不是您可以或应该在Perl中担心的事情。

See also "How can I make my Perl program take less memory?" 另请参见“如何使我的Perl程序占用更少的内存?”

In general, perl won't release memory back to the system. 通常,perl不会将内存释放回系统。 It keeps its own pool of memory in case it is required for another purpose. 万一出于其他目的而需要,它会保留自己的内存池。 This happens a lot because lexical data is often used in a loop, for instance your $arrref1 variables refer to a million-element array. 这经常发生,因为词法数据经常在循环中使用,例如, $arrref1变量引用一百万个元素的数组。 If the memory for those arrays was returned to the system and reallocated every time around the loop there would be an enormous speed penalty 如果将这些阵列的内存返回到系统并在每次循环时重新分配,那么将会有巨大的速度损失。

As I wrote, 170MB isn't a lot, but you can reduce the footprint by dropping your big temporary arrays and adding the list directly to the hash element. 如我所写,170MB并不多,但是您可以通过删除大型临时数组并将列表直接添加到hash元素来减少占用空间。 As it stands you are unnecessarily keeping two copies of each array 就目前而言,您不必要每个数组保留两个副本

It would look like this 看起来像这样

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM