Метка: php zval

  • ZVAL: фундаментальная структура данных в PHP. Часть 1 — устройство и оптимизации

    Содержание

    1. Что такое ZVAL и зачем он нужен

    ZVAL (zend value) — это базовая C-структура в ядре PHP, которая отвечает за:

    • Хранение значения любой переменной (числа, строки, объекта и т.д.)
    • Определение типа данных (integer, string, array и др.)
    • Управление памятью через подсчёт ссылок (refcount)
    • Оптимизацию работы с переменными (флаги, кэширование)

    Где используется: Каждая переменная в PHP, включая элементы массивов и свойства объектов, внутри представлена как ZVAL.

    2. Подробный разбор структуры ZVAL

    В PHP 8 структура ZVAL значительно оптимизирована по сравнению с PHP 5. Рассмотрим её основные компоненты:

    2.1. Основные поля структуры

    // Упрощённое определение zval в PHP 8+
    typedef struct _zval_struct {
        zend_value        value;    // Само значение (union)
        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;                  // Для хэш-таблиц
            uint32_t     cache_slot;            // Кэш
            uint32_t     lineno;                // Номер строки (для AST)
        } u2;
    };
    

    2.2. Типы данных (zval.type)

    Основные типы, определенные в ядре PHP:

    КонстантаТипРазмер
    IS_LONGЦелое число8 байт (64-bit)
    IS_DOUBLEЧисло с плавающей точкой8 байт
    IS_STRINGСтрокаЗависит от длины
    IS_ARRAYМассив24 байт + элементы
    IS_OBJECTОбъект40 байт + свойства

    3. Управление памятью и refcount

    Механизм подсчёта ссылок (refcount) — ключевой аспект работы ZVAL:

    // Пример 1: Простое присваивание
    $a = "Hello";  // zval: value="Hello", type=IS_STRING, refcount=1
    $b = $a;       // Теперь refcount=2
    
    // Пример 2: Изменение с refcount > 1
    $b = "World";  // Создаётся новый zval для $b (copy-on-write)
    

    4. Эволюция ZVAL: PHP 5 vs PHP 8

    Сравнение реализации в разных версиях PHP:

    ХарактеристикаPHP 5PHP 8
    Размер структуры24 байта16 байт
    Хранение строкОтдельный указательВстроено в union
    Подсчёт ссылокВсегда отдельныйОбъединён с типом

    5. Практика: отладка ZVAL

    Используем xdebug для анализа:

    function debug_zval_demo() {
        $var = "Test";
        $ref = &$var;
        xdebug_debug_zval('var');
    }
    // Выведет: var: (refcount=2, is_ref=1)='Test'
    

    6. Ключевые оптимизации

    • Copy-on-Write (COW): Копирование только при изменении
    • Interned strings: Хранение одинаковых строк в одном экземпляре
    • Immutable массивы: Оптимизация для массивов-констант

    В следующей части мы рассмотрим практические примеры работы с ZVAL и разберём тонкости управления памятью.

  • Внутреннее устройство PHP: глубокий разбор структуры zval

    Zval (Zend value) — фундаментальная структура данных в ядре PHP, ответственная за хранение и обработку всех переменных. В этой статье мы детально разберем её эволюцию и современную реализацию.

    Историческая эволюция

    Версия PHPРазмер zvalКлючевые изменения
    PHP 5.624 байтаУниверсальный подсчет ссылок, избыточность
    PHP 7.016 байтОптимизация хранения скаляров, новые флаги
    PHP 8.216 байтДополнительные оптимизации JIT

    Сравнение производительности

    // Тест создания 1 млн zval-ов (в нс)
    PHP 5.6: 2400 ns
    PHP 8.2: 800 ns (ускорение 3x)

    Структура zval в PHP 8

    struct _zval_struct {
        zend_value value;    // 8 байт (union)
        union {
            struct {
                zend_uchar type;        // Тип данных
                zend_uchar type_flags;  // Поведенческие флаги
                zend_uchar const_flags; // Константность
                zend_uchar reserved;    // Выравнивание
            } v;
            uint32_t type_info;         // Альтернативное представление
        } u1;                          // 4 байта
        union u2 {                     // 4 байта (служебные данные)
            uint32_t next;
            // ... другие поля
        };
    }; // Всего 16 байт

    Типы данных и их хранение

    • Скаляры (int, float, bool) — хранятся напрямую в zend_value
    • Строки — указатель на zend_string (отдельная структура в heap)
    • Массивы — указатель на HashTable
    • Объекты — указатель на zend_object

    Ключевые оптимизации

    1. Отказ от refcount для скаляров

    В PHP 7+ целые числа и булевы значения больше не используют подсчет ссылок, что устраняет накладные расходы на их копирование.

    2. Copy-On-Write для сложных структур

    $a = [1,2,3]; // Создается HashTable (refcount=1)
    $b = $a;      // Только увеличивается refcount
    $b[] = 4;     // Реальное копирование при изменении

    3. Встроенное кеширование хешей

    Строки хранят предвычисленные хеши, что ускоряет операции сравнения и поиска в хеш-таблицах.

    Практическое применение

    Для разработчиков расширений

    // Создание zval в расширении
    zval my_zval;
    ZVAL_LONG(&my_zval, 42);
    
    // Доступ к значению
    if (Z_TYPE(my_zval) == IS_LONG) {
        zend_long value = Z_LVAL(my_zval);
    }

    Оптимизации для веб-приложений

    • Используйте строгие типы (strict_types=1)
    • Избегайте избыточного копирования массивов
    • Освобождайте память unset() для больших структур

    Заключение

    • Zval в PHP 8 — высокооптимизированная структура
    • Понимание её устройства помогает писать эффективный код
    • Оптимизации PHP 7+ дают до 3x прирост производительности