PHP: enter the Matrix

Let’s look at the symbols.

Zend values (Zvals) Permalink to heading Zend values (Zvals)

PHP stores all variables in “zvals”. Those containers hold specific pieces of information (e.g the var type, the value). As containers, Zvals need to be stored somewhere in the memory.

The PHP engine uses these elements as internal value representation.

So, be aware that zvals are not accessible from your php code. You need to read the source.

It might be hard to understand Zvals though. The documentation says it represents an arbitrary PHP value.

If it does not make sense, that’s normal. It’s pretty abstract.

PHP 7 upheaval and the lifecycle Permalink to heading PHP 7 upheaval and the lifecycle

The zval memory usage is much much better in PHP 7 than in PHP 5. There’s a good reason for that. PHP 7 completely rewrites the zval implementation.

PHP makes two passes every time it runs:

  1. it parses and compiles source code (your files) to build machine code
  2. it executes the compiled code (run-time)

Zvals store values and types. This way, PHP can use this information when compiling. Otherwise, the engine would not be able to get this information at this time.

But how does PHP use zvals? Permalink to heading But how does PHP use zvals?

Here is the structure of zvals:

struct _zval_struct {
    zend_value value;
    union {
        struct {
                zend_uchar type,
                zend_uchar type_flags,
                zend_uchar const_flags,
                zend_uchar reserved)
        } v;
        uint32_t type_info;
    } u1;
    union {
        uint32_t var_flags;
        uint32_t next;                 // hash collision chain
        uint32_t cache_slot;           // literal cache slot
        uint32_t lineno;               // line number (for ast nodes)
        uint32_t num_args;             // arguments number for EX(This)
        uint32_t fe_pos;               // foreach position
        uint32_t fe_iter_idx;          // foreach iterator index
    } u2;


Zvals use “unions”. A union logically contains several members so the engine indexes all members in the same memory location.

But the engine uses only one member at a time. As a result, the union size is the size of its largest member.

The refactored Zend Engine (PHPNG) needs less memory partly because of the new zval implementation. Less duplication leads to less memory allocation.

The RAM access is 100 times slower than the CPU access. There is a latency. PHP 7 leverages the benefits of CPU caches and sharing mechanisms to reduce the number of memory accesses.

PHP Assignments Permalink to heading PHP Assignments

Developers need to store data in complex structures such as strings, objects, and arrays.

PHP makes assignments by value. You might think it needs to copy the value every time but that would be very expensive, especially with large arrays. Instead of doing this, it shares values between Zvals.

In PHP 7, this sharing mechanism is even better because of the new zval size and structure. It needs fewer pointers.

Opcodes Permalink to heading Opcodes

PHP 7 has a better compilation than PHP 5. It is slower but cleaner. There are a lot of internal operations to optimize memory usage and allocation.

The opcode (operation code) is the result of parsing. The engine pre-compiles your source code into bytecode before it’s sent to the interpreter.

The compile-time is higher but PHP 7 significantly reduces the execution time (runtime).

You can store your compiled code with Opcache, this way, PHP 7 is a speedster comparing to PHP 5.

Wrap up Permalink to heading Wrap up

PHP is faster than ever thanks to version 7 of the Matrix :). The fundamental elements such as zvals have been deeply reshaped leading to a global momentum.

Credits photo: Markus Spiske

I do my best to update all my contents, but keep it mind that "PHP: enter the Matrix" has been published many months ago.