Метка: оптимизация

  • Введение в сборку мусора в PHP

    1. Что такое сборка мусора и зачем она нужна?

    Сборка мусора (Garbage Collection, GC) — это автоматическое освобождение памяти, которую программа больше не использует.

    Без GC разработчикам приходилось бы вручную освобождать память (как в C/C++ с malloc/free).

    С GC PHP сам определяет, когда объекты больше не нужны, и очищает их.

    Зачем это нужно?

    • Избегать утечек памяти
    • Упрощать разработку (не нужно следить за каждым объектом)
    • Повышать стабильность долгоживущих процессов (например, PHP-FPM)

    2. Как PHP управляет памятью?

    PHP использует гибридный подход:

    1. Референсный подсчет (Reference Counting) – основной механизм.
    2. Циклический сборщик (Cycle Collector) – для сложных случаев.

    Как работает референсный подсчет?

    • Каждая переменная (zval) хранит счетчик ссылок (refcount).
    • Когда refcount достигает 0, память освобождается мгновенно.

    Пример:

    $a = new stdClass(); // refcount = 1
    $b = $a;            // refcount = 2
    unset($a);          // refcount = 1
    unset($b);          // refcount = 0 → память освобождена
    

    Когда референсного подсчета недостаточно?

    При циклических ссылках (когда объекты ссылаются друг на друга):

    $a = new stdClass();
    $b = new stdClass();
    $a->child = $b;  // $a ссылается на $b  
    $b->parent = $a; // $b ссылается на $a  
    unset($a, $b);   // refcount останется = 1 → утечка!
    

    Здесь на помощь приходит циклический сборщик.

    3. Референсный подсчет vs. Tracing GC (как в Java/C#)

    КритерийPHP (Reference Counting)Java/C# (Tracing GC)
    СкоростьБыстро (освобождает сразу)Медленнее (сканирует всю память)
    ПамятьТратит меньше ОЗУТребует больше памяти
    ЗадержкиНет «stop-the-world»Возможны паузы (GC STW)
    Циклические ссылкиТребует отдельный сборщикНаходит автоматически

    Вывод:

    • Референсный подсчет быстрее, но не справляется с циклами.
    • Tracing GC (как в Java) универсальнее, но требует больше ресурсов.

    4. Когда включается GC в PHP?

    GC в PHP работает в два этапа:

    1. Мгновенное освобождение (при refcount=0).
    2. Циклический сборщик (запускается при условиях):

    Когда срабатывает циклический сборщик?

    • При достижении порога (по умолчанию 10 000 потенциальных циклов).
    • При вызове gc_collect_cycles() (ручной запуск).
    • При завершении скрипта (если gc_enable=On).

    Настройки в php.ini:

    zend.enable_gc = On       ; Включить GC  
    gc_probability = 1        ; Вероятность запуска (1/100)  
    gc_divisor = 100  
    gc_max_roots = 10000      ; Порог для активации
    

    5. Краткий обзор изменений в PHP 8.3

    В PHP 8.3 GC получил небольшие оптимизации:

    • Уменьшены накладные расходы на отслеживание ссылок.
    • Улучшена интеграция с JIT (меньше пауз при сборке).
    • Оптимизирован алгоритм обхода объектов (быстрее на сложных графах).

    Что не изменилось:

    • Основной механизм (референсный подсчет + циклы).
    • API (gc_enable(), gc_collect_cycles()) остался прежним.

    Вывод

    • PHP использует референсный подсчет для быстрого освобождения памяти.
    • Циклический сборщик чинит утечки из-за взаимных ссылок.
    • В PHP 8.3 GC стал немного быстрее, но принцип работы не изменился.

    Следующая статья: Референсный подсчет в PHP — как именно работает refcount? 🚀