Вы написали скрипт или даже большой какой-то проект. Наверняка в нем используются регулярные выржания. И наверняка вы захотели бы оптимизировать ваш проект по скорости выполнения. Начните с опимизации "регулярок". Для этого вам очень пригодится прагма use re, с опцией 'debug', и возможно qr//.
Я не буду подробно рассказывать о qr//, для предварительной компиляции regexp'ов, (может быть в другой раз), а расскажу о такой полезной прагме как: use re с опцией debug. В скриптах она используется так:
#!/usr/bin/perl -w
use strict;
use re 'debug';
При включении этой прагмы все регулярные выражения будут выдавать о себе много интересной информации. И оценивая эту информацию можно повысить скорость обработки входных данных для вашего регэкспа.
Предположим у вас есть вот такой вот код, который извлекает кодировку из заголовка content-type:
1 #!/usr/bin/perl -w
2 use strict;
3 use re 'debug';
4
5 my $string='text/html; charset=UTF-8;';
6
7 my $reg=qr/charset=(\w+-\w+)/i;
8
9 if($string=~/$reg/)
10 {
11 print "find $1\n";
12 } else {
13 print "not\n";
14 }
Запустим его на выполнение с прагмой use re 'debug':
Compiling REx `charset=(\w+-\w+)'
size 14 Got 116 bytes for offset annotations.
first at 1
1: EXACTF <charset=>(4)
4: OPEN1(6)
6: PLUS(8)
7: ALNUM(0)
8: EXACTF <->(10)
10: PLUS(12)
11: ALNUM(0)
12: CLOSE1(14)
14: END(0)
stclass "EXACTF <charset=>" minlen 11
Offsets: [14]
1[8] 0[0] 0[0] 9[1] 0[0] 12[1] 10[2] 13[1] 0[0] 16[1] 14[2] 17[1] 0[0] 18[0]
Matching REx "charset=(\w+-\w+)" against "text/html; charset=UTF-8;"
Matching stclass "EXACTF <charset=>" against "text/html; charset=UTF-8;"
Setting an EVAL scope, savestack=7
11 <tml; > <charset> | 1: EXACTF <charset=>
19 <arset=> <UTF-8;> | 4: OPEN1
19 <arset=> <UTF-8;> | 6: PLUS
ALNUM can match 3 times out of 2147483647...
Setting an EVAL scope, savestack=7
22 <arset=UTF> <-8;> | 8: EXACTF <->
23 <arset=UTF-> <8;> | 10: PLUS
ALNUM can match 1 times out of 2147483647...
Setting an EVAL scope, savestack=7
24 <arset=UTF-8> <;> | 12: CLOSE1
24 <arset=UTF-8> <;> | 14: END
Match successful!
find UTF-8
Freeing REx: `"charset=(\\w+-\\w+)"'
Теперь немного изменим наше выражение:
7 my $reg=qr/charset=([\w,-]+)/i;
и снова запустим с отладкой:
Compiling REx `charset=([\w,-]+)'
size 21 Got 172 bytes for offset annotations.
first at 1
1: EXACTF <charset=>(4)
4: OPEN1(6)
6: PLUS(19)
7: ANYOF{i}[,\-0-9A-Z_a-z+utf8::IsWord](0)
19: CLOSE1(21)
21: END(0)
stclass "EXACTF <charset=>" minlen 9
Offsets: [21]
1[8] 0[0] 0[0] 9[1] 0[0] 16[1] 10[6] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 17[1] 0[0] 18[0]
Matching REx "charset=([\w,-]+)" against "text/html; charset=UTF-8;"
Matching stclass "EXACTF <charset=>" against "text/html; charset=UTF-8;"
Setting an EVAL scope, savestack=7
11 <tml; > <charset> | 1: EXACTF <charset=>
19 <arset=> <UTF-8;> | 4: OPEN1
19 <arset=> <UTF-8;> | 6: PLUS
ANYOF{i}[,\-0-9A-Z_a-z+utf8::IsWord] can match 5 times out of 2147483647...
Setting an EVAL scope, savestack=7
24 <arset=UTF-8> <;> | 19: CLOSE1
24 <arset=UTF-8> <;> | 21: END
Match successful!
find UTF-8
Freeing REx: `"charset=([\\w,-]+)"'
Разница очевидна. Второе выражение отработало быстрее. Как на этапе компиляции (выделено жирным), так и на этапе выполнения (второму варианут потребовалось 2 прохода, в то время как первому 3!). Так - методом подбора можно оптимизировать некоторые свои регэкспы, или во всяком случае увидеть наиболее неэффективные из них.
Еще некоторую информацию вы сможете почерпнуть отсюда.



Комментировать