Модель, достаточная для приложения
Переменная PHP указывает на значение, а внутренний контейнер runtime отслеживает тип и использование. Простое присваивание большого массива не обязано немедленно копировать все элементы: копирование проявляется при изменении одной из разделяемых структур. Это copy-on-write, а не гарантия нулевой стоимости любой операции.
Ссылка через & меняет семантику: два имени становятся связаны с одним контейнером. Используйте её только когда общий изменяемый слот действительно является контрактом. Случайная ссылка в foreach способна повредить последующую итерацию, поэтому переменную после цикла разумно отвязать.
Путь памяти
Что удерживает память
Главный риск Pulse — накопить все события в массиве ради удобного array_map. Второй риск — сохранить замыкание, которое захватило тяжёлый объект. Третий — статический кэш без политики размера. memory_get_usage и memory_get_peak_usage помогают локализовать этап, но объяснение требует профиля объектов и формы данных.
unset удаляет имя из текущей таблицы переменных, но объект останется, если на него ведёт другая ссылка. Поэтому сначала ищут владельца и срок жизни, затем уменьшают граф состояния. Повышение memory_limit только отодвигает отказ.
Циклы и GC
Счётчик ссылок освобождает большинство значений сразу, когда владельцев не осталось. Циклический граф — например, объект родителя с детьми, которые ссылаются назад, — требует обнаружения циклов сборщиком мусора. Это не означает, что gc_collect_cycles нужно вызывать после каждой строки.
Для долгоживущего worker измерьте память после одинаковых пакетов. Стабилизация обычно допустима; устойчивый рост требует профилирования. Явный вызов GC рассматривают после подтверждения циклов и измерения паузы, а не как универсальную оптимизацию.
Два эксперимента
Сравните пик памяти для массива из всех строк и генератора, который отдаёт по одному событию. Затем присвойте большой массив второй переменной и отдельно измените вложенный элемент: измерьте момент фактического роста. Эксперимент должен фиксировать версию PHP и одинаковый вход.
Не превращайте наблюдение одного patch-релиза во внутренний API. Архитектура опирается на ограниченный объём живых данных, а не на точный размер zval или порядок внутренних оптимизаций.
Лаборатория
Обработайте файл из ста тысяч синтетических событий при batchSize 500. Выведите пик памяти и число сбросов, затем намеренно добавьте массив allEvents и покажите разницу.
- Граница памяти объясняется размером пакета.
- В производственном коде нет gc_collect_cycles без измерения.
- После foreach по ссылке переменная отвязана.
Закрепите материал
Отметка, заметка, чек-лист и ответы остаются в localStorage этого браузера и не отправляются в аналитику.
Перелинковка со справочником
Проверка актуальности
- php.nethttps://www.php.net/manual/en/language.types.phpПервичный источник для актуализации фактов. Адрес приведён как текст и не является активной ссылкой.
- php.nethttps://www.php.net/manual/en/features.gc.phpПервичный источник для актуализации фактов. Адрес приведён как текст и не является активной ссылкой.
Текст и схемы созданы для этого самоучителя без воспроизведения страниц, иллюстраций и листингов приложенной книги. Проверено: .