Pull to refresh

Comments 30

UFO just landed and posted this here
UFO just landed and posted this here
там ссылочка есть, где написано, как
Операция конкатенации не оптимизирована

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

Если вы используете конкатенацию строк, то в результате будете делать те же странные вещи, что и в 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-компилятор и что из этого вышло. Ну и про дальнейшие планы, конечно.
UFO just landed and posted this here
«C» не написан на ассемблере, он написан на самом себе (по крайней мере это верно для GCC).
UFO just landed and posted this here

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

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

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

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


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


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

Большое спасибо за полезную информацию.
Sign up to leave a comment.