Почему этот regex называл substcont чрезмерным количеством раз?

Это больше вне любопытства, чем что-либо еще, поскольку мне не удается найти любую полезную информацию о Google об этой функции (ЯДРО:: substcont)

В профилировании и оптимизации некоторых старых, медленных, XML, анализирующий код, я нашел, что следующий regex называет substcont 31 раз в течение каждого раза, когда строка выполняется, и занимание огромного количества времени:

Вызовы: в 10000 Раз: 2,65 с вызовы Sub: в 320000 Раз в нижних индексах: 1.15s'

  $handle =~s/(>)\s*(<)/$1\n$2/g;
  # spent  1.09s making 310000 calls to main::CORE:substcont, avg 4µs/call
  # spent  58.8ms making  10000 calls to main::CORE:subst, avg 6µs/call

По сравнению со сразу предыдущей строкой:

Вызовы: в 10000 Раз: вызовы Sub на 371 мс: в 30000 Раз в нижних индексах: 221 мс

  $handle =~s/(.*)\s*(<\?)/$1\n$2/g;
    # spent   136ms making 10000 calls to main::CORE:subst, avg 14µs/call
    # spent  84.6ms making 20000 calls to main::CORE:substcont, avg 4µs/call

Количество вызовов substcont довольно удивительно, особенно видя, поскольку я думал бы, что второй regex будет более дорогим. Это, очевидно, почему профилирование является Хорошей Вещью ;-)

Я впоследствии изменился оба, они выравнивают для удаления ненужного backrefs с поразительными результатами для строки плохого поведения:

Время Calls:10000: вызовы Sub на 393 мс: в 10000 Раз в нижних индексах: 341 мс

$handle =~s/>\s*</>\n</g;
  # spent   341ms making 10000 calls to main::CORE:subst, avg 34µs/call
  • Так, мой вопрос - почему оригинал должен был выполнять Столько вызовов к substcont, и что substcont даже делает в regex механизме, который занимает много времени?
7
задан paulw1128 24 May 2010 в 16:52
поделиться

1 ответ

substcont - внутреннее имя Perl для «итератора подстановки». Что-то связано с s /// . Судя по той небольшой информации, которую я располагаю, кажется, что substcont срабатывает при выполнении обратной ссылки. То есть, когда присутствует $ 1 . Вы можете немного поиграть с этим, используя B :: Concise.

Вот коды операций простого регулярного выражения без обратной ссылки.

$ perl -MO=Concise,-exec -we'$foo = "foo";  $foo =~ s/(foo)/bar/ig'
1  <0> enter 
2  <;> nextstate(main 1 -e:1) v:{
3  <$> const[PV "foo"] s
4  <#> gvsv[*foo] s
5  <2> sassign vKS/2
6  <;> nextstate(main 1 -e:1) v:{
7  <#> gvsv[*foo] s
8  <$> const[PV "bar"] s
9  </> subst(/"(foo)"/) vKS
a  <@> leave[1 ref] vKP/REFC
-e syntax OK

И один с.

$ perl -MO=Concise,-exec -we'$foo = "foo";  $foo =~ s/(foo)/$1/ig'
1  <0> enter 
2  <;> nextstate(main 1 -e:1) v:{
3  <$> const[PV "foo"] s
4  <#> gvsv[*foo] s
5  <2> sassign vKS/2
6  <;> nextstate(main 1 -e:1) v:{
7  <#> gvsv[*foo] s
8  </> subst(/"(foo)"/ replstart->9) vKS
9      <#> gvsv[*1] s
a      <|> substcont(other->8) sK/1
b  <@> leave[1 ref] vKP/REFC
-e syntax OK

Это все, что я могу предложить. Вы можете попробовать Rx , старый отладчик регулярных выражений mjd.

4
ответ дан 7 December 2019 в 14:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: