PHP 2999 ~ 3 мин.

Встраивание функций в PHP

Встраивание функций в PHP

В программировании встраивание функций (англ. Function Inlining) - это способ оптимизации, при котором вызов функции заменяется непосредственно её телом

Встраивание функций - это важная оптимизация, однако оказываемый эффект на производительность может быть различным. 

Современный PHP работает быстро! Он имеет ряд особенностей для повышения производительности, такие как OPCache, JIT и другие улучшения на этапе компиляции, чтобы сделать интеллектуальную оптимизацию для приложения PHP.

На данный момент PHP имеет более 30 функций , которые используют специальные коды OPCodes или встроены иным образом для повышения производительности.

Одним из примеров, демонстрирующих этот эффект, является функция strlen. Она возвращает длину заданной строки, и PHP пытается выполнить оптимизацию с упреждением.


if (strlen('Test') < 2) {
    echo "Test";
}

В этом фрагменте функция strlen вызывается для статической строки, и PHP может полностью исключить этот блок, поскольку длина строки Test фиксирована, и значение сравнения также является статическим. Это лучше видно с помощью дампа OPCode .

До оптимизации


php -d opcache.opt_debug_level=0x10000 test.php

 

0000 JMPZ bool(false) 0002
0001 ECHO string("Test")
0002 RETURN int(1)

 После оптимизации


php -d opcache.opt_debug_level=0x20000 test.php


0000 RETURN int(1)

Этот пример работает и в обратном направлении, избавляясь от ненужных OPCodes JMP / JMPZ / JMPNZ, которые в противном случае использовались бы в блоке if.  


if (strlen('Test') < strlen('Test Test')) {
    echo "Test";
}


0000 ECHO string("Test")
0001 RETURN int(1)

Поскольку strlen('Test') < strlen('Test Test') всегда будет true, оптимизированный OPCode не будет содержать никаких переходов.

Полные имена функций

А вы замечали в каком-нибудь чужом коде, в начале файла, где идет объявление используемых классов, так же есть объявление функций с помощью оператора use? Ну знаете, что-то типа:


..

use function is_array;
...

Зачем объявлять функции, если они, вроде как, уже известны интерпретатору PHP?

Так вот, когда вызов функции выполняется внутри пространства имен, движок не может использовать специальную обработку, потому что возможно, что функция с тем же именем будет объявлена ​​позже в программе.


namespace Foo;

if (strlen('Test') < strlen('Test Test')) {
    echo "Test";
}

Обратите внимание, как блок if находится внутри пространства имен Foo. Дамп OPCode показывает, что PHP не применил здесь особую обработку: 


php -d opcache.opt_debug_level=0x20000 test.php


0000 INIT_NS_FCALL_BY_NAME 1 string("Foo\strlen")
0001 SEND_VAL_EX string("Test") 1
0002 V1 = DO_FCALL_BY_NAME
0003 INIT_NS_FCALL_BY_NAME 1 string("Foo\strlen")
0004 SEND_VAL_EX string("Test Test") 1
0005 V2 = DO_FCALL_BY_NAME
0006 T0 = IS_SMALLER V1 V2
0007 JMPZ T0 0009
0008 ECHO string("Test")
0009 RETURN int(1)

Большинство проектов на PHP используют пространства имен, и чтобы вернуть особую обработку, имена функций могут быть снабжены префиксом обратной косой черты (\) или как раз, объявление псевдонимами с use function. Их часто называют «Полностью определенными именами функций» - (Fully-Qualified Function Names) или же FQFN.

Ускорение вашего приложения

В настоящее время единственный способ ускорить вызовы функций - это убедиться, что глобальные функции вызываются правильным квалифицированным способом. Это утомительное ручное действие. Вы можете сделать это одним из двух способов:


namespace Foo;
if (\strlen('Test') < \strlen('Test Test')) {
    echo "Test";
}

или


namespace Foo;
use strlen;
if (strlen('Test') < strlen('Test Test')) {
    echo "Test";
}

Оба приведенных выше фрагмента сигнализируют движку о том, что вызов strlen действительно предназначен для внутренней функции strlen, что позволяет движку продолжать и встраивать их. С FQFN движок снова может применить свою магию:    


0000 ECHO string("Test")
0001 RETURN int(1)

Есть еще варианты объявление автоматических реализация, в виде подключения сторонних пакетов типа  php_backslasherFunctionFQNReplacer и пр. Так же можно объявить declare(no_dynamic_functions=1) в начале вашего файла.

При вызове внутренних функций PHP, особенно с встраиваемыми функциями, всегда указываются полные имена функций, чтобы обеспечить для них оптимизацию движка.


Список функций со специальной обработкой

Все следующие функции имеют особую обработку в Zend Engine и могут нести большую пользу, если вызываются как полностью определенное имя функции.



Что думаешь?

Категории
  • PHP 65
  • Заметки 15
  • Безопасность 3
  • Флуд 2
  • Nginx 2
  • ИТ новости 2
  • Видео 1
  • Docker 1
  • Roadmap 1
  • Архитектура 0

Хочешь поддержать сайт?

Делаем из мухи слона

sergeymukhin.com

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

Релизы PHP 8.4

Дата Релиз
8 Июня 2024 Альфа 1
20 Июня 2024 Альфа 2
04 Июля 2024 Альфа 3
16 Июля 2024 Feature freeze
18 Июля 2024 Бета 1
01 Августа 2024 Бета 2
15 Августа 2024 Бета 3
29 Августа 2024 RC 1
12 Сентября 2024 RC 2
26 Сентября 2024 RC 3
10 Октября 2024 RC 4
24 Октября 2024 RC 5
07 Ноября 2024 RC 6
21 Ноября 2024 GA

Что нового?