Анатомия zval: Основные компоненты (PHP 7+)

PHPПроизводительностьzvalвнутренние механизмыОптимизацияПрограммирование

В этой статье мы детально разберём структуру zval в современных версиях PHP, начиная с революционного PHP 7. Вы узнаете, как организовано хранение переменных на низком уровне и какие оптимизации были внедрены.

2.1. Основные компоненты zval

Структура _zval_struct

struct _zval_struct {
    zend_value value;    // Основное значение (64 бита)
    union {
        struct {
            zend_uchar type;         // Тип данных (IS_LONG, IS_STRING и др.)
            zend_uchar type_flags;    // Флаги поведения типа
            zend_uchar const_flags;   // Флаги константности
            zend_uchar reserved;      // Зарезервировано
        } v;
        uint32_t type_info;           // Альтернативное представление
    } u1;                            // 32 бита
    union u2 {                       // 32 бита (служебные данные)
        uint32_t next;               // Для управления хеш-таблицами
        uint32_t cache_slot;         // Кеширование
        uint32_t lineno;             // Номер строки (для ошибок)
        uint32_t num_args;           // Количество аргументов
        uint32_t fe_pos;             // Позиция в foreach
        // ... другие служебные поля
    };
}; // Всего 16 байт

1. Компонент value (zend_value)

Тип Поле Размер Описание
Целое lval 64 бита Для типов IS_LONG, IS_BOOL
Дробное dval 64 бита Для IS_DOUBLE
Указатель str 64 бита Для строк (IS_STRING)
Указатель arr 64 бита Для массивов (IS_ARRAY)

2. Компонент u1 (метаданные типа)

  • type - определяет базовый тип данных (IS_LONG, IS_STRING и др.)
  • type_flags - дополнительные флаги поведения:
    • IS_TYPE_REFCOUNTED (требует подсчета ссылок)
    • IS_TYPE_COPYABLE (поддерживает Copy-On-Write)
    • IS_TYPE_IMMUTABLE (неизменяемый тип)
  • const_flags - флаги константности

3. Компонент u2 (служебные данные)

Этот компонент используется для различных оптимизаций:

  • next - связь элементов в хеш-таблицах
  • cache_slot - кеширование для быстрого доступа
  • lineno - отладка (номер строки в исходном коде)
  • num_args - информация о вызовах функций

Практический пример

// Создание zval с целым числом
zval my_zval;
ZVAL_LONG(&my_zval, 42);

// Доступ к данным
if (Z_TYPE(my_zval) == IS_LONG) {
    zend_long value = Z_LVAL(my_zval); // 42
    php_printf("Значение: %ld\n", value);
}

Продолжение следует в следующей статье цикла...