Function Inlining in Zend Engine

Published On2021-04-01

Zend Engine (PHP) special function inlining

Modern PHP is fast! It has several performance features such as OPCache, JIT, and other improvements at the compilation step to make smart optimizations for many PHP applications.

Inspecting the OPCodes is an easy way to make sure that PHP can make the best optimizations as possible. With the OPCodes listed, it becomes clearer if a given PHP snippet takes the shortest number of OPCodes necessary to perform the intended task.

PHP has several over 30 such functions at the moment, that make use of special OPCodes, or otherwise inlined to improve performance.


One example to show this effect is the strlen function. It returns the length of a given string, and PHP tries to optimize preemptively.

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

In this snippet, the strlen function is called on a static string literal, and PHP can eliminate this block completely because the length of the Test string is fixed, and the comparison value is also a static value.

This is better revealed with the OPCode dump.

Prior to optimization

php -d opcache.opt_debug_level=0x10000 test.php
0000 JMPZ bool(false) 0002
0001 ECHO string("Test")
0002 RETURN int(1)

After optimization

php -d opcache.opt_debug_level=0x20000 test.php
0000 RETURN int(1)

This example works the other way too, by getting rid of the unnecessary JMP/JMPZ/JMPNZ OPCodes that would be otherwise used in a PHP if block.

if (strlen('Test') < strlen('Test Test')) {
    echo "Test";
}
0000 ECHO string("Test")
0001 RETURN int(1)

Because strlen('Test') < strlen('Test Test') always evaluates to true, the optimized OPCode does not contain any jumps.

Fully-Qualified Function Names

One caveat with the special function handling is that when a special function call is made inside a namespace, the engine cannot use the special handling because it is possible that a function with the same name is declared later in the program.

namespace Foo;

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

Notice how the if block is inside the Foo namespace. The OPCode dump reveals that PHP did not apply the special handling here:

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)

Most of the modern PHP code bases use namespaces, and to bring back the special handling, the function names can be prefixed with a backslash (\), or aliased with the use function clause. They are often called as "Fully-Qualified Function Names".

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

or

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

Both snippets above signal the engine that the strlen calls are indeed for the internal strlen function, which allows the engine to go ahead and inline them.

With FQFNs, the engine can again apply its magic:

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

The gist of this article is that, when calling PHP internal functions, specially functions with inlining features, always make the fully-qualified function names to enable engine optimizations on them.

List of Functions with Special Handling

All of the following functions have special handling within the Zend Engine, and can benefit from them if called as a Fully-Qualified Function Name.

List up to date until PHP 8.1. Source

Recent Articles on PHP.Watch

All ArticlesFeed
Writing better Regular Expressions in PHP

Writing better Regular Expressions in PHP

How to write more readable, self-explanatory, and effective regular expressions in PHP.
PHP's new convention on using namespaces for extensions

PHP's new convention on using namespaces for extensions

A recent RFC passed in favor of using a namespace for PHP extensions.
How to compile PHP from source on Debian/Ubuntu - Beginner's guide

How to compile PHP from source on Debian/Ubuntu - Beginner's guide

Beginner's guide to compile PHP from the source, on Ubuntu/Debian with up to date instructions for PHP 8 and up.
Subscribe to PHP.Watch newsletter for monthly updates

You will receive an email on last Wednesday of every month and on major PHP releases with new articles related to PHP, upcoming changes, new features and what's changing in the language. No marketing emails, no selling of your contacts, no click-tracking, and one-click instant unsubscribe from any email you receive.