我目前正在运行一个perl程序,我必须将100万行文本文件分解成块(每块大小在50到50,000行之间),然后运行一些计算等。现在,我将所有数据加载到array1中。我使用array2并使用它来提取我需要的数据块。然后我做我需要在阵列2上执行的操作,然后返回并抓住下一组。
示例数据
A,blah1,blah2
A,blah6,blah7
A,blah4,blah5
B,blah2,blah2
所以我会把前三个拿到阵列2中,对它们进行排序,然后继续下一组。我的程序开始时效果非常好,但后来经历了严重的减速。
50K需要50秒,100k需要184秒,150k需要360秒,200k需要581秒,并且只会随着程序的继续而呈指数级下降(500k线处为4500秒)
不,我不能为这个项目使用数据库,有什么建议吗?
my @Rows1=<FILE>;
my $temp = @Rows1;
for($k = 0; $k < $temp; $k++)
{
my @temp2array = ();
my $temp2count = 0;
my $thisrow = $Rows1[$k];
my @thisarray = split(',', $thisrow);
my $currcode = $thisarray[0];
my $flag123 = 0;
$temp2array[$temp2count] = $thisrow;
$temp2count++;
while ($flag123 == 0)
{
$nextrow = $tuRows1[$k + 1];
@nextarray = split(',', $nextrow);
if ($currcode eq $nextarray[0])
{
$temp2array[$temp2count] = $nextrow;
$k++;
$temp2count++;
}
else
{
$flag123 = 1;
}
}
}
我编辑的代码更像是下面的答案,我有这些时间:
50k = 42,100k = 133,150k = 280,200k = 467,250k = 699,300k = 978,350k = 1313
它不完全保持线性,按照这种趋势,这个编程仍然需要14000+秒。我将调查代码的其他部分
答案 0 :(得分:2)
将整个大文件加载到内存中会降低速度,因为操作系统需要开始交换虚拟内存页面。在这种情况下,最好只处理您需要的文件部分。
在您的情况下,您似乎在第一个字段中处理具有相同值的行,因此您可以执行以下操作:
my @lines = ();
my $current_key = '';
while (<FILE>) {
my ($key) = split /,/; # get first column
if ($key ne $current_key) {
# new key. Process all the lines from the previous key.
if (@lines > 0) {
process(@lines);
}
@lines = ();
$current_key = $key;
}
push @lines, $_
}
# don't forget the lines from the last key
if (@lines > 0) {
process(@lines);
}
这样,你只需要在内存中存储足够的行来组成一个组。
(我假设输入数据是按键排序或组织的。如果不是这样,你可以在文件中进行多次传递:第一次传递以查看需要处理的键,以及后续传递收集与每个密钥相关的行。)
答案 1 :(得分:0)
运行您显示的代码是否会减速?如果没有,问题在于实际处理每个@ temp2array块的代码,可能还有一些变量仍然从以前的块中遗留了数据。