
Почему одна вставка в PHP‑массив может стоить 100 мс
dead4w 7 минут назад Почему одна вставка в PHP‑массив может стоить 100 мс Сложный 7 мин 120 PHP * Программирование * Туториал Из песочницы На примере PHP хорошо видно, как внутренние оптимизации динамически...
<5 — 2026'da uzaya kaç SpaceX Starship fırlatması ulaşacak?
Значимый прорыв формирует отрасль ИИ: dead4w 7 минут назад Почему одна вставка в PHP‑массив может стоить 100 мс Сложный 7 мин 120 PHP * Программирование * Туториал Из песочницы На примере PHP хорошо видно, как внутренние оптимизации динамически типизированного языка развиваются и усложняются. PHP‑массив выглядит универсальным, но внутри него скрыто множество оптимизаций и ветвлений, в их числе оптимизации для хранения и работы с массивами: Packed List & HashTable. Взаимодействие между ними и copy‑on‑write дают иногда неожиданное и непрозрачное поведение с точки зрения PHP программиста.
Примеры гиперболизированы и редко встречаются в реальности. Они намеренно показывают худший кейс для наглядности. Массив — это List, HashTable или что‑то ещё?
Технические детали
В PHP массив — Швейцарский нож. Внутри данные могут храниться по‑разному: это может быть упакованный список: , а может быть ассоциативный массив (хеш‑таблица): . Это создает довольно интересные ситуации, например посмотрите на код ниже.
// Создаем последовательный массив без дырок $length = 10000000; // 10 000 000 $arr = ; for ($i = 0; $i < $length; $i++) { $arr = $i; } elapsedDebug(function () use (&$arr, $length) { // Вставляем элемент, который порождает разрыв между ключами $arr = 123; // ИЛИ Вставляем элемент со строковым ключом // $arr = 123; }); // PHP 5. 007 ms | Peak RAM: 1426 MB // PHP 7. 956 ms | Peak RAM: 1090 MB // PHP 8.
026 ms | Peak RAM: 1154 MB // PHP 8. 345 ms | Peak RAM: 898 MB // PHP 8. 610 ms | Peak RAM: 898 MB // PHP 8.
Отраслевые последствия
213 ms | Peak RAM: 898 MB // PHP 8. 777 ms | Peak RAM: 898 MBВ данном примере мы создаем обычный список , а после добавляем заведомо большой ключ, по сравнению с последним. Тем самым обычный упакованный массив‑список 0-10_000_000 превращается в список с дыркой0-10_000_000, 100_000_000Такая же ситуация при создании строкового ключа.
Из‑за этого строчка с вставкой одного лишь элемента может занимать до 100ms, что очень даже много. Если после вставки попытаться вставить ещё один ключ, например 1_000_000_000 или другой строковый ключ, то вставка будет моментальной. Внутри функции elapsedDebug — ничего интересного кроме вывода.
Внутри нашей анонимной функции, в которой происходит вставка — тоже пусто. Это происходит поскольку Xdebug обычно отслеживает трейсы и функции, а не присвоение переменных. А включение отслеживания присвоений раздувает трейсы до гигабайтов.
Событие, по словам экспертов, усилит конкуренцию в сфере ИИ.





