修改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循环中变量占用的内存。
注意:我不能使用任何其他脚本或编程语言。
答案 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永远不会能够重用那个记忆。