Perl: добавляемый файл медленно читается - PullRequest
0 голосов
/ 15 января 2020

Я написал довольно большой (400 строк) скрипт, который выполняет одно задание: читать и анализировать (используя регулярные выражения) полезные строки в очень большом файле журнала, к которому непрерывно добавляются новые строки (записано примерно 40 ГБ) каждый день).

Основной l oop выглядит следующим образом:

#Main loop through the log file. Runs the loop until '<information_type' is found.
if ($input_type eq 'clear') {
 while (my $line = <$inputfh>) {
     next unless ($line =~ /$xml_entry/);
     load_XML($line, $inputfh);
 }
}
elsif ($input_type eq 'zip') {
#Same as load_XML but with print $localfh $line.
$inputfh->getline();
my @tmp;
while (my $line = <$inputfh>) {
    print ($localfh $line);
    next unless ($line =~ /$xml_entry/);
    push @tmp, $.;
    push @tmp, tell($localfh);
    push @tmp, $line;
    while ($line !~ /$xml_exit/)
    {
        $line = $inputfh->getline();
        print $localfh $line;
        push @tmp, $line;
    }
    cross_grep(\@tmp);
    @tmp = ();
}
close $localfh;
}
sub load_XML {
    #This is a very odd construct, but a zipped file apparently cannot provide a trustworthy tell.
    #Tellhandle is the inputfh in the case of an unzipped and the outputfh in the case of a zipped.
    my ($line, $tellhandle) = @_;
    my @tmp;
    push @tmp, $.;
    push @tmp, tell($tellhandle);
    push @tmp, $line;
    while ($line !~ /$xml_exit/)
    {
        $line = $inputfh->getline();
        print $localfh $line if $localfh;
        push @tmp, $line;
    }
    #Cross grep for the target words given as argument. If all words are found, the array is valid and printed.
    cross_grep(\@tmp);
    return;
}

Скрипт использует множество обходных путей, чтобы охватить множество вариантов использования, которые мы можем иметь, но по существу it:

  • Открывает файл, который может быть либо простым текстом, либо zip-файлом
  • В случае zip-файла использует PerlIO :: gzip, чтобы открыть его и прочитать как обычный дескриптор файла
  • В случае открытого текста использует простое открывание ("$ filehandle" "<$ file") </li>
  • Передает строки через регулярное выражение, которое ищет точку входа в XML
  • Записывает и печатает строки этого XML до тех пор, пока не найдет свою точку выхода
  • Поиск в строках указанных c слов (функция cross_grep ())
  • Имеет много маленьких распечаток с бухгалтерией Tell ($ filehandle) и печать номера строки

Проблема заключается в том, что в настоящее время этот сценарий распаковывает, читает и анализирует сжатый 10 ГБ журнал примерно за 3 минуты, , в то время как он совершенно не способен читать и анализировать непрерывно добавляемый открытый текст регистрируйте даже 1/5 от этой скорости.

Когда я использую top на сервере, на котором находятся скрипты, он говорит, что загрузка ЦП составляет около 65% для zip-файл, но никогда не превышает 25% для открытого текста и обычно составляет около 13%. Помимо PerlIO :: gzip, используемого для файлов журналов, нет разницы в потоке, регулярные выражения одинаковы, функциональные возможности или строки не меняются ни на один бит.

На самом деле, сжатые журналы принимают время записать все разархивированные строки в другой текстовый файл. И все же я могу извлекать журналы только в течение 20 минут из живого журнала (постоянно добавляя новые строки), в то время как я могу получить 5 часов заархивированного файла в одно и то же время.

Я повернул голову вокруг это 100 раз, но мне кажется, что это невозможно с вычислительной точки зрения. Если проблема в том, что текстовый файл постоянно добавляется и это как-то мешает Perl читать, то почему это не так, когда я выполняю поиск grep или меньше в этом файле?

Мне кажется, что Perl естественным образом ограничивает чтение файла во время его добавления (что происходит буквально каждые 0,05 секунды), но мне это нужно, чтобы не делать и использовать как можно больше ресурсов процессора и быстро завершить поиск sh, не останавливая при этом все время.

Является ли Perl удушающим показанием для добавленного открытого текста? Если да, могу ли я как-то заставить его использовать как можно больше энергии? Или есть другая причина, которую я не вижу?

Как распаковка, чтение и запись в открытом тексте может быть быстрее, чем просто чтение приложенного файла в открытом тексте?

...