Замедление в большом массиве Perl - PullRequest
1 голос
/ 26 января 2011

В настоящее время я использую Perl-программу, в которой мне нужно взять текстовый файл с 1 миллионом строк, разбить его на куски (где-то между 50 и 50000 строк на кусок) и выполнить некоторые вычисления и тому подобное.Прямо сейчас я загружаю все данные в array1.Я беру array2 и использую его для извлечения только тех кусков данных, которые мне нужны.Затем я делаю то, что мне нужно, для массива 2, а затем возвращаюсь и беру следующий набор.

пример данных

A, blah1, blah2

A, blah6, blah7

A, blah4, blah5

B, blah2, blah2

Поэтому я бы взял первые три в массив 2, отсортировал их, а затем перешел к следующемузадавать.Моя программа работает довольно хорошо и эффективно с самого начала, но позже она испытывает серьезное замедление.

50K занимает 50 секунд, 100k - 184 секунды, 150k - 360 секунд, 200k - 581 секунда, и она получает толькоэкспоненциально хуже, поскольку программа продолжается (4500 секунд в строке 500k)

Нет, я не могу использовать базу данных для этого проекта, какие-либо предложения?

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+ секунд.Я исследую другие части кода

Ответы [ 2 ]

2 голосов
/ 26 января 2011

Загрузка всего большого файла в память замедлит вас, так как вашей ОС потребуется начать обмениваться страницами виртуальной памяти. В таких случаях лучше всего иметь дело только с тем фрагментом файла, который вам нужен.

В вашем случае вы, кажется, обрабатываете строки, которые имеют одно и то же значение в первом поле вместе, поэтому вы можете сделать что-то вроде:

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

Таким образом, вы сохраняете в памяти только достаточно строк, чтобы составить одну группу.

(Я предполагаю, что входные данные отсортированы или организованы по ключу. Если это не так, вы можете сделать несколько проходов по файлу: первый проход, чтобы увидеть, какие ключи вам нужно будет обработать, и последующие проходы собрать строки, связанные с каждым ключом.)

0 голосов
/ 26 января 2011

Имеет ли замедление только выполнение кода, который вы показываете? В противном случае проблема заключается в коде, который фактически обрабатывает каждый кусок @ temp2array, возможно, некоторая переменная (и) все еще имеет данные, оставшиеся от предыдущих блоков.

...