Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Регулярные выражения > как отключить стандартные оптимизации


Автор: zyxerr 5.12.2008, 12:30
Добрый день!
1) Как отключить стандартные оптимизации (описанные у Фридла, глава "стандартные оптимизации") в движке регулярных выражений? 
2) Можно ли их выборочно отключать?
3) где в исходниках Perl они прописаны?

Автор: tolkien 6.12.2008, 01:06
ОФФТОП
Может вам ненужно этого делать. Все же не зря люди их делали. Они помогают когда текст небольшой. Работает очень быстро. Отсюда простой вывод для оптимизации работы  текста с рег выражениями. Нужно оптимизировать сам текст. Т.е разбивать на мелкие части и их обрабатывать рег выраж.

Автор: zyxerr 8.12.2008, 11:48
Добрый день, tolkien
.
Я понимаю, что их не зря делали smile Но Фридл пишет, что многие оптимизации могут также и негативно влиять на скорость исполнения. Особенно это касается случаев, когда и сама запись шаблона подвергается ручной оптимизации.  Он называет эти случаи "чрезмерной оптимизацией" (с. 270)
.
попробую поискать на perlmonks

Добавлено @ 11:52
"Т.е разбивать на мелкие части и их обрабатывать рег выраж. "
.
а можно поподробнее? т.е. если у меня строка вида:
.
"text text text text text text text text text text text text text text text text text text text "
.
и некоторый набор регулярных выражений, которыми нужно обработать эту строку,
то нужно разбить строку на массив:
text 
text 
text 
text 
text 
text 
text 
text 
text 
и каждый элемент массива обработать этими правилами? Разве это даст выигрыш по времени? или я не так понял

Автор: amg 8.12.2008, 12:52
zyxerr, нужно еще учитывать, перл и его машина регулярных выражений постоянно развиваются и всяческие неоптимальности в более новых версиях устраняются. 

Приведу пример. Когда-то писали, что нежадный поиск -- это нехорошо, медленно. Так оно и было, помнится, сам проверял сколько то лет назад. А недавно еще раз проверил на perl 5.8.8 типичную задачу, поиск между тэгами в большой html. И с удивлением обнаружил, что среди вариантов
m|<tag>(.*?)</tag>|; m|<tag>([^<]*)</tag>|; m|<tag>((?:.(?!</tag>))*.)</tag>|;
первый из них (обыкновенный нежадный поиск) оказался быстрее всех.

Думаю, что авторы перла Фридла тоже читали, и, возможно, уже все хорошо.

Автор: tolkien 8.12.2008, 23:16
Цитата(zyxerr @ 8.12.2008,  11:48)
Добрый день, tolkien
...
то нужно разбить строку на массив:
text 
text 
text 
text 
text 
text 
text 
text 
text 
и каждый элемент массива обработать этими правилами? Разве это даст выигрыш по времени? или я не так понял

Даст потрясающий выигрыш в производительности. Потому что прежде чем обработать строку. Рег выражение ее сначала оптимизирует. Если взять например функцию index то ее производительность от длины текста в котором производиться поиск не меняется. А у рег выражений она катастрофически падает. Чем длинее текст тем сильнее падает. 

Автор: zyxerr 9.12.2008, 11:52
Кстати, пишу вот:

Код

$| = 1;

open (OU1,">1.txt");
for (1 .. 1000000) {print OU1 "text\n"}

open(IN1, "1.txt");
while(<IN1>){$c++ if /text/}

print $c; <> 

.
угадайте чему равно $c?  -  999424 (!), странно, а почему не миллион?

Автор: amg 9.12.2008, 12:58
Мысль об отключении буферирования -- верная, только отключать его нужно было не STDOUT'у, а OU1.
select OU1;
$| = 1;
# Побочный эффект -- print без указания файлхэндлера будет печатать в OU1
...

Автор: ginnie 9.12.2008, 13:10
amg, может лучше

Код

use IO::Handle;
autoflush OU1 1;


Автор: amg 9.12.2008, 13:39
ginnie, а чем лучше? (это не риторический вопрос, просто я никогда не пользовался autoflush и не знаю преимуществ)

Автор: ginnie 9.12.2008, 13:44
amg, лучше тем, что не меняется дескриптор вывода по-умолчанию.

Автор: zyxerr 9.12.2008, 14:55
amg, большое спасибо, не знал такой особенности насчет Select OU1

Автор: tolkien 9.12.2008, 22:28
Цитата(zyxerr @ 9.12.2008,  11:52)
Кстати, пишу вот:

Код

$| = 1;

open (OU1,">1.txt");
for (1 .. 1000000) {print OU1 "text\n"}

open(IN1, "1.txt");
while(<IN1>){$c++ if /text/}

print $c; <> 

.
угадайте чему равно $c?  -  999424 (!), странно, а почему не миллион?

Во первых. Зачем вам отключать буферизацию? Вы знаете что код с буферизацией значительно быстрее работает чем код с отключенной буферизацией? И в вашем коде есть грубейшая ошибка. В результате который вы получаете такой странный результат. В любой литературе по программированию в разделе работы с файлами. Написано ОБЯЗАТЕЛЬНО ЗАКРЫВАЙТЕ ОТКРЫТЫЕ ФАЙЛОВЫЕ МАНИПУЛЯТОРЫ КОГДА ОНИ ВАМ БОЛЬШЕ НЕ НУЖНЫ!!!

Код

$| = 1;

open (OU1,">1.txt");
for (1 .. 1000000) {print OU1 "text\n"}
close OU1;
open(IN1, "1.txt");
while(<IN1>){$c++ if /text/}

print $c;
close IN1;


Вывод: 1000000

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)