Comments 30
Операция конкатенации не оптимизирована
А почему, кто-нибудь в курсе? Вроде принцип-то похожий.
Если вы используете конкатенацию строк, то в результате будете делать те же странные вещи, что и в PHP 5.
Выделяет буфер для «Мне нравится»;
и далее по тексту.
Хотя если конкатенация небольшая — то думаю заморачиваться даже не стоит.
Я это прочитал. Мой вопрос был про то, по каким техническим причинам при конкатенации осталось то же поведение. Она используется чаще encapsed-строк, при этом результат получается аналогичный.
Я алгоритма не знаю, рассуждаю чисто логически, и не претендую на истину.
Допустим, есть такая конкатенация.
$str = $substr_1 . ' подстрока 2 ' . func_foo() . $substr_4;
Я так подозреваю, что с точки зрения работы с памятью это будет некая последовательность операций.
$buf_str_1 = $substr_1 . ' подстрока 2 ';
$buf_func_foo = func_foo(); // ключевой момент - вычисляемое выражение
$buf_str_2 = $buf_str_1 . $buf_func_foo;
$buf_str_3 = $buf_str_2 . $sub_str_4;
$str = $buf_str_3;
unset($buf_str_1);
unset($buf_func_foo);
unset($buf_str_2);
unset($buf_str_3);
Скорее всего в деталях ошибся. Тут лучше обратиться к первоисточникам (там более что я php7 пока даже и не юзал). Может кто поправит.
Дальше хотел написать, что конкатенацию нельзя оптимизировать скорее всего из-за возможного наличия вычисляемых выражений (в моём примере вызов функции func_foo). Но заметил, что DarthLegiON уже это сделал ниже. Что лишь подтверждает мою мысль (которую я изначально не озвучил, да, признаю).
Все чуть проще. Разница в способе разбора. Возьмем две строки:
$str1 = "I like big $foo and I can not $bar";
$str2 = 'I like big ' . $foo . ' and I can not ' . $bar;
Результатом разбора будет примерно следующее:
T_VARIABLE = "T_ENCAPSED_AND_WHITESPACE T_VARIABLE T_ENCAPSED_AND_WHITESPACE T_VARIABLE";
T_VARIABLE = T_CONSTANT_ENCAPSED_STRING . T_VARIABLE . T_CONSTANT_ENCAPSED_STRING . T_VARIABLE;
то есть в первом случае у нас есть как минимум токен "
, который можно спокойно учитывать при построении ast. То есть по итогу все это выражение будет заменено опкодом ZEND_FAST_CONCAT. То есть даже в случае вызовов функций мы все равно получим итоговую длину строки до непосредственно конкатенации.
Во втором же случае у нас все не так очевидно, PHP с версии 7.0 хоть и имеет LALR(1) парсер, но это уже надо учитывать контекст или оптимизировать итоговый ast чего делать увы не стали. Но это всего-лишь вопрос времени.
Насчёт __toString() не сообразил, значит видимо ошибся насчёт вычисляемых выражений.
Хоть на истину и не претендовал. Хорошо, что поправили.
Спасибо. Действительно может оптимизируют когда-нибудь.
$str = $substr_1 . ' подстрока 2 ' . func_foo() . $substr_4;
это же
$__tmp001 = func_foo();
$str = $substr_1 . ' подстрока 2 ' . $__tmp001 . $substr_4;
и в итоге те же
$__tmp001 = func_foo();
$str = "$substr_1 подстрока 2 $__tmp001 $substr_4";
Не видно ни одной проблемы оптимизировать ровно тем же образом.
Не видно ни одной проблемы оптимизировать ровно тем же образом.
весь вопрос в разборе кода. Для строк все очень просто, а для конкатенации чуть сложнее. Ну то есть есть даже merge request для этого но по какой-то причине его не стали пока вмердживать в мастер.
Да я уже понял, что вопрос не в вычисляемых значениях.
Насчёт __toString() не сообразил
понятно, что и насчёт других магических вызовов.
Пользователь Fesor же ответил выше.
Хотя ошибался не только я, но Вы поправили и там ))
А насчёт "проблемы оптимизировать" Сергей ответил уже, дважды.
Я даже полез было выяснять, что же за ZEND_FAST_CONCAT, напоролся на https://github.com/php/php-src/blob/master/ext/opcache/Optimizer/block_pass.c. Дальше решил в исходниках не разбираться и поверить Сергею Протько на слово ))
Сергей, можете пояснить, если opcache выключен, будет ли работать описанная оптимизация (хотя бы на encapsed-строках)?
У нас просто сейчас php5 и apc, но интересно же, что там в семёрке, на будущее.
Я понимаю, что вопросы детские, так и есть, простите. Но полагаю, что это интересно будет не только мне.
Да и прочие выражения собственно тоже, вроде
"str1 " . ($a ? $b : $c) . " str2"
переходит в
$__tmp002 = $a ? $b : $c;
"str1 $__tmp002 str2"
Там довольно любопытно и познавательно. В том числе, про попытки сделать JIT-компилятор и что из этого вышло. Ну и про дальнейшие планы, конечно.
между "программным обеспечением" и "языком программирования" есть разница, как вы верно заметили. В приведенном вами тексте говорится именно о программном обеспечении с названием PHP (можно было бы еще упомянуть zend engine но это уже реализация виртульной машины а не весь комплекс). Если вы хотите "программное обеспечение позволяющее запускать код на языке PHP, написанное на java" например, то у вас есть JPHP. Заметьте что название отличается.
Ключи вставляются в массив только по возрастанию.
Вроде ключи должны инкрементироваться с 0.
Чтобы к массиву применялась оптимизация, описанная в том абзаце, это не обязательно. Обязательно по возрастанию, но не более того.
Чуть более подробнее про эти оптимизации (и с картинками) можно почитать тут:
Она есть и тут https://habrahabr.ru/company/mailru/blog/308240/
Улучшение производительности PHP 7