Удар производительности Perl между двумя распространенными методами регулярных выражений для обрезки строк? - PullRequest
4 голосов
/ 27 октября 2011

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

Первый метод - быстрый однострочный:

$word =~ s/^\s+|\s+$//g;

Второй метод немного длиннее, но делает то же самое:

$word =~ s/^\s+//;
$word =~ s/\s+$//;

Длямои тесты, у меня был сценарий, прочитанный из файла с 40 миллионами строк, обрезая каждую (ничего кроме этого не делает).Средняя длина строки составляет менее 20 байтов.

Первый метод занял в среднем 87 секунд.
Второй метод занял в среднем 27 секунд.
Без обработки (только чтение строки, продолжение) занимает в среднем 16 секунд.

Первый метод (первый проход) будет сопоставлять либо все начальные или конечные пробелы, затем удалять его, затем сопоставлять и удалять начальные / конечные пробелы на другой стороне.
Второй метод сопоставляет и удаляетвесь начальный пробел, затем сопоставляет и удаляет все конечные пробелы.

Возможно, я ошибаюсь, но почему второй метод будет в 3 раза быстрее первого?

Ответы [ 3 ]

11 голосов
/ 27 октября 2011

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

echo " hello " |perl -Mre=debug -ple 's/^\s+|\s+$//g'
echo " hello " |perl -Mre=debug -ple 's/^\s+//;s/\s+$//'
5 голосов
/ 27 октября 2011

Имеет смысл, что закрепленные шаблоны без обратного отслеживания могут быть оптимизированы ПУТЬ лучше (по сути, одно последовательное сканирование вперед / назад, начиная с известной позиции символа);

Скорее всего, что 'option' (|) отключает оптимизатор, и вы получаете стандартный возврат в обратном направлении, что очень плохо, потому что может возникнуть много пробелов, которые не заканчиваются

2 голосов
/ 27 октября 2011

Я подозреваю, что регулярное выражение Perl может оптимизировать вторую версию с помощью статического анализа шаблона. Например, он может увидеть, что /^foo/ должно совпадать в начале строки. Если совпадение не удается, нет смысла перебирать остальные символы в строке, проверяя совпадения.

По умолчанию символ «^» гарантированно соответствует только началу строки, символ «$» - только концу (или перед новой строкой в ​​конце), а Perl выполняет определенные оптимизации при условии, что строка содержит только одну строку.

Источник (Выделение мое.)

Первая версия является более сложным выражением и не так легко оптимизируется.

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