Как стать автором
Обновить

Комментарии 30

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
##php?
там ссылочка есть, где написано, как
Операция конкатенации не оптимизирована

А почему, кто-нибудь в курсе? Вроде принцип-то похожий.

Если вы используете конкатенацию строк, то в результате будете делать те же странные вещи, что и в 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 чего делать увы не стали. Но это всего-лишь вопрос времени.

Была где-то глубоко мысль, что возможно michael_vostrikov прав в том плане, что всё-таки в будущем возможно будет оптимизировать и конкатенацию (именно в плане анализа контекста перед конкатенацией) в некоторых случаях, не содержащих вызовов функций, но я старался исходить из текста статьи (см. мой первый коммент в ветке).
Насчёт __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, но интересно же, что там в семёрке, на будущее.
Я понимаю, что вопросы детские, так и есть, простите. Но полагаю, что это интересно будет не только мне.

Могу предположить, что разница в том, что в encapsed на этапе компиляции известно, сколько нужно вставить строк, а при конкатенации это значение может меняться. Плюс конкатенировать можно любые значения, в том числе динамически преобразуемые в строки, вызовы функций и т. д., а энкапсить — только переменные или свойства объектов. За счет их (условно) статической природы можно заранее узнать, что, каких размеров и в каком количестве нужно вставлять в строку.
Свойства объектов могут быть не явно прописанными в объекте, а отрабатывать через магический метод __get — а значит может появиться всё что угодно, хоть до получения каждый раз разного значения при попытке читать «свойство объекта». Так что функции сильно ближе к делу чем кажутся.

Да и прочие выражения собственно тоже, вроде
тринарника
"str1 " . ($a ? $b : $c) . " str2"

переходит в
$__tmp002 = $a ? $b : $c;
"str1 $__tmp002 str2"

Подскажите пожалуйста, если PHP5 используется как модуль Apache — «парсинг/компиляция» php-файла происходит при каждом http-запросе или имеет место какое-либо кеширование?

Да, конечно. Opcache для этого и нужен: он хранит данные в разделяемой памяти. Частота/поведение инвалидации зависит от настроек в php.ini

КДПВ отлично коррелирует с ником переводчика)

С оригинальными постами, к сожалению, не коррелирует. Её там просто нет.

Месяца 3 назад разработчик виртуальной машины PHP Дмитрий Стогов (Chief Performance Engineer в Zend Technologies) рассказал у нас на митапе о том, как он с коллегами ускорял PHP 7:



Там довольно любопытно и познавательно. В том числе, про попытки сделать JIT-компилятор и что из этого вышло. Ну и про дальнейшие планы, конечно.
НЛО прилетело и опубликовало эту надпись здесь
«C» не написан на ассемблере, он написан на самом себе (по крайней мере это верно для GCC).
НЛО прилетело и опубликовало эту надпись здесь

между "программным обеспечением" и "языком программирования" есть разница, как вы верно заметили. В приведенном вами тексте говорится именно о программном обеспечении с названием PHP (можно было бы еще упомянуть zend engine но это уже реализация виртульной машины а не весь комплекс). Если вы хотите "программное обеспечение позволяющее запускать код на языке PHP, написанное на java" например, то у вас есть JPHP. Заметьте что название отличается.

Ключи вставляются в массив только по возрастанию.

Вроде ключи должны инкрементироваться с 0.

Чтобы к массиву применялась оптимизация, описанная в том абзаце, это не обязательно. Обязательно по возрастанию, но не более того.


Чуть более подробнее про эти оптимизации (и с картинками) можно почитать тут:


http://jpauli.github.io/2016/04/08/hashtables.html

Большое спасибо за полезную информацию.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий