perl没有释放内存,可能是什么原因?

时间:2014-11-28 09:10:27

标签: perl dispose

修改1 : 我在perl文件中遵循逻辑,(添加了输出文件处理程序)。

for (my $i = 0; $i < 10; $i++) {
        my $outputFile=$i."_out";
        open(outputHandler, ">$outputFile") or die "Couldn't open output file: $!";
        my $filePath = $i;
        open(Rfile_handle, $filePath) or die("Could't open input file: $!");
        while (<Rfile_handle>) {
            my $line = $_;
            #Do processing - line by line. Read global variable - no edit/update
            #add required fields in my $outputLine variable
            print outputHandler "$outputLine\n";
        }
        close Rfile_handle;
        close outputHandler;
    }

我仍然看到同样的行为。我看到内存使用量不断增加。我要杀死进程并从执行的最后一行重新运行程序。 这正是我正在做的事情。除了从json分配和提取数据的逻辑部分外,代码没有变化。现在,我们能推断出什么吗?或者我做错了什么?

编辑结束1

我是perl的新手程序员。我在c#中使用了代码。 我有大约10个文件,每个大约5GB。我需要阅读&amp;逐个处理它们。我的系统RAM大小只有4GB。所以,我使用以下方式读取for循环中的文件,

for (int i = 0; i < 10; i++) {
    my $filePath = i;
    open(Rfile_handle, $filePath) or die("Could't open input file: $!");
    while (<Rfile_handle>) {
        my $line = $_;
        //Do processing - line by line
    }
    close Rfile_handle;
}

当我看到它显示的任务管理器时,内存使用量正在增加。 完成一个文件后,不应该perl释放内存并将其恢复为下一个文件,就像c#为我做的那样?正如任务管理器所示,它不会释放内存。我可以以某种方式处置/解除分配内存吗?

我已经尝试了undef,但它没有释放内存。

我该怎么办?什么是在perl中读取如此巨大的文件的最佳方法? 我想要一种方法来重用for循环中变量占用的内存。

注意:我不能使用任何其他脚本或编程语言。

2 个答案:

答案 0 :(得分:6)

不要担心。 Perl看起来使用更多内存,因为它使用内部内存管理。它仍然在内部释放和重用。只是出于显而易见的原因,它必须扩展到内存占用的最大大小。

一般来说,确保perl的方式尽可能高效:

  • 词法范围变量(尤其是数组/散列) - perl可以在不再使用时找出它们。 (它使用引用计数来跟踪。)。

  • 使用while循环逐行读取文件,而不是foreach循环。 (首先将整个文件读入临时数组)

更一般地说 - 你可能应该使用3参数打开,因为两个参数是坏的风格。

所以你应该在代码中执行:

open ( my $input_fh, "<", $filepath ) or die $!;

while( my $line = <$input_fh> ) {
    #do stuff; 
}

$output_fh会在'for'循环结束时将ref count降为零并关闭并取消分配。

在while循环中处理文件时,您存储了什么? Perl不会 - 默认情况下 - 使用等于文件大小的内存,除非你以某种方式“保存”整行?

哦,你有一个错误:

my $filePath=i;

这会将您的$filePath设置为名为i的文件,但该文件不起作用。开启:

use strict;
use warnings;

你会被告知这类问题。 (for循环中的同一问题。i在perl中不是有效的变量名,您应该使用$i

另见:

http://learn.perl.org/faq/perlfaq3.html#How-can-I-free-an-array-or-hash-so-my-program-shrinks-

http://perldoc.perl.org/perlfaq3.html#How-can-I-make-my-Perl-program-take-less-memory%3f

由于perl如何使用引用计数,perl中存在'gotcha' - 您可以创建循环引用链。因为它们仍然被引用,所以perl不会垃圾收集。如果您遇到此问题,可以使用weaken()中的Scalar::Util

答案 1 :(得分:2)

如果您按照问题中的代码逐行进行处理(而不是将整个文件内容存储到数组,散列或其他数据结构中),并且消耗的内存要大得多而不是每行的数据量,那么你很可能在处理代码中有内存泄漏 - 你使用的引用计数永远不会降到0的变量(可能是由于数据结构中的循环引用),所以Perl永远不会能够重用那个记忆。