loading...
Cover image for PHP: enter the Matrix

PHP: enter the Matrix

jmau111 profile image Julien Maury Updated on ・3 min read

Let's look at the symbols.

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

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?

Here is the structure of zvals:

struct _zval_struct {
    zend_value value;
    union {
        struct {
            ZEND_ENDIAN_LOHI_4(
                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;
};
Enter fullscreen mode Exit fullscreen mode

Source

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

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

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

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

Posted on by:

jmau111 profile

Julien Maury

@jmau111

Practise what you preach.

Discussion

pic
Editor guide
 

A little typo: it executes the compiled code instead of compilated code.