Почему substr-lvalue быстрее, чем substr с четырьмя аргументами? - PullRequest
4 голосов
/ 08 мая 2020

Из этого вопроса мы сравниваем эти два варианта,

substr( $foo, 0, 0 ) = "Hello ";
substr( $foo, 0, 0, "Hello " );

В нем мы обнаруживаем, что substr -lvalue быстрее . На что Икегами сказал:

Как 4-arg substr медленнее, чем lvalue substr (который должен создавать магический скаляр и требует дополнительных операций) ??? - ikegami

По правде говоря, я также предполагал, что он будет намного медленнее, и просто упомянул об этом, потому что он был поднят кем-то другим. Исключительно из любопытства,

Почему substr -lvalue быстрее, чем 4-arg substr в приведенном выше сценарии использования?

Ответы [ 2 ]

4 голосов
/ 08 мая 2020

Начиная с 5.16.0, вариант lvalue + assign был оптимизирован до варианта с 4 аргументами (хотя обнуленная операция присваивания N OOP все еще находилась в пути выполнения до 5.20.0, что немного замедлило его ).

4 голосов
/ 08 мая 2020

Это был просто плохой результат теста.

Когда я воспроизводил ваши результаты, я использовал perl на Unbuntu на Windows Susbsytem для Linux. Скажем так, производительность этой системы зависит от внешних факторов.

Даже при использовании собственной сборки для Windows (Strawberry Perl) на том же компьютере я получаю огромные различия в результатах:

                   Rate        substr substr_valute   multiconcat
                  Rate substr_valute        substr   multiconcat
substr_valute 6997958/s            --           -0%          -27%
substr        7007667/s            0%            --          -26%
multiconcat   9533733/s           36%           36%            --

                   Rate        substr substr_valute   multiconcat
substr        6795650/s            --           -0%          -10%
substr_valute 6805545/s            0%            --          -10%
multiconcat   7526593/s           11%           11%            --

                    Rate        substr substr_valute   multiconcat
substr         7513339/s            --          -22%          -28%
substr_valute  9693997/s           29%            --           -6%
multiconcat   10367639/s           38%            7%            --

                    Rate        substr   multiconcat substr_valute
substr         8791152/s            --          -13%          -14%
multiconcat   10139954/s           15%            --           -1%
substr_valute 10240638/s           16%            1%            --

Время настолько мало, и машина слишком занята, чтобы получать точные показания.

(Здесь есть смысл сказать о микрооптимизации где-то ... )

Я ненавижу запускать тесты на моем общем веб-хосте linux, но обычно он дает гораздо более последовательные результаты. Сегодняшний день не стал исключением.

                   Rate        substr substr_valute   multiconcat
substr        4293130/s            --           -3%          -13%
substr_valute 4407446/s            3%            --          -11%
multiconcat   4938717/s           15%           12%            --

                   Rate substr_valute        substr   multiconcat
substr_valute 4289732/s            --           -2%          -16%
substr        4356113/s            2%            --          -15%
multiconcat   5096889/s           19%           17%            --

(я использовал -3 вместо 100_000_000.)

Все различия составляют 3% или меньше, что несущественно. Насколько я могу судить, один не медленнее другого.

На самом деле никакой разницы ожидать не стоит. Как указал Дэйв Митчелл, substr( $foo, 0, 0 ) = "Hello "; оптимизирован до чего-то практически эквивалентного substr( $foo, 0, 0, "Hello " ); начиная с версии 5.16 (с улучшением в 5.20).

$ perl -MO=Concise,-exec -e'substr( $foo, 0, 0, "Hello " );'
1  <0> enter
2  <;> nextstate(main 1 -e:1) v:{
3  <#> gvsv[*foo] s
4  <$> const[IV 0] s
5  <$> const[IV 0] s
6  <$> const[PV "Hello "] s
7  <@> substr[t2] vK/4
8  <@> leave[1 ref] vKP/REFC
-e syntax OK

$ perl -MO=Concise,-exec -e'substr( $foo, 0, 0 ) = "Hello ";'
1  <0> enter
2  <;> nextstate(main 1 -e:1) v:{
3  <$> const[PV "Hello "] s
4  <#> gvsv[*foo] s
5  <$> const[IV 0] s
6  <$> const[IV 0] s
7  <@> substr[t2] vKS/REPL1ST,3
8  <@> leave[1 ref] vKP/REFC
-e syntax OK

(Единственная разница - это порядок, в котором операнды передаются, что сигнализируется с помощью флага REPL1ST.)

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