5 миллионов совпадений с регулярным выражением съедает мой процессор [Perl] - PullRequest
0 голосов
/ 17 декабря 2011

У меня есть приложение, которое запускает несколько процессов.Каждый процесс загружает файл HTML и пытается найти, присутствует ли в нем шаблон, что-то вроде этого:

OUTER:
while(my ($prov,$arr_ref) = each(%{$self->{TAGS}})) {
    foreach my $tag (@{$arr_ref}) {
        if ($html =~ m/\Q$tag\E/i) {
            $provider = $prov;
            last OUTER;
        }
    }
}

$self->{TAGS} ключ - это имя шаблона, а значение - это ссылка на массив со строками (скаляры).

Я профилировал программу и обнаружил, что эта часть:

$html =~ m/\Q$tag\E/i

заставляет мой процессор подскочить до 100%.Если я удаляю его, он едва достигает 10%.

Я имею в виду только один подход, который превращает все скаляры (строки) внутри каждого массива ref в скомпилированное регулярное выражение (qr/.../).Я полагаю, что это не так сильно улучшится, поскольку, на самом деле, проблема заключается в том, что регулярное выражение выполняет поиск по всем HTML-страницам, размер которых может достигать сотен байтов.

Что можно сделать, чтобы улучшить этораздел?

ПОДРАЗДЕЛ: из-за ответов ниже, и некоторые тесты, которые я сделал, я уточню свой вопрос, проблема не в регулярном выражении, я уже попробовал indexзадолго до того, как я задал этот вопрос, также попробовал скомпилированное регулярное выражение с qr//, эта проблема, с размером html-файлов, содержимым $html является текст HTML, иногда его маленький, а иногда большой, поэтому проблема здесьЧТО ТАКОЕ ЛУЧШИЙ СПОСОБ (с точки зрения ресурсов ...) НАЙТИ, ЕСЛИ СТРОКА ВНУТРИ БОЛЬШОЙ (ПОЗВОЛЯЕТ 1 МБ НА РАЗМЕРЕ) СТРОКУ?

Спасибо.

Ответы [ 2 ]

4 голосов
/ 17 декабря 2011

\ Q означает, что ваше регулярное выражение может быть заменено на index . Для поиска без учета регистра оба тега $ html и $ должны быть преобразованы в нижний регистр как можно раньше.

my $htmllc=lc($html);
while () {
  ...
  if (index($htmllc,$tag)>-1) {
   ...
  }
}

P.S. Вы должны попробовать сравнить несколько решений.

4 голосов
/ 17 декабря 2011

Использование index должно повысить производительность, поскольку вы избавитесь от всех накладных расходов, связанных с использованием регулярных выражений.Пожалуйста, сделайте тест!

$html_searchable = lc ($html);

...    

while ( ... ) {
  foreach ( ... ) {
    if (index ($html_searchable, lc ($tag)) > -1) {
      ... # we got a match
    }
  }
}

Если вы хотите увеличить его еще больше, вы должны хранить все свои $tag в виде строчных букв, чтобы вам не нужно было lc одна и та же строка несколько раз.

Документация

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...