Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Задачи

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про PHP: garbage, collection

Есть ли в PHP сборщик мусора? Как работает refcount?

Этот вопрос проверяет понимание системы управления памятью в PHP, механизма подсчета ссылок и работы циклического сборщика мусора.

Короткий ответ

Да, в PHP есть сборщик мусора. Основной механизм - подсчет ссылок (refcount), который автоматически освобождает память когда переменная больше не используется. Для циклических ссылок используется циклический сборщик мусора. Refcount отслеживает сколько переменных ссылаются на значение в памяти. Когда refcount достигает нуля, память immediately освобождается. Для циклических ссылок, которые не могут быть удалены через refcount, используется отдельный алгоритм обнаружения и очистки.

Длинный ответ

Система управления памятью в PHP

Основные компоненты

  • Подсчет ссылок (refcount) - основной механизм

  • Циклический сборщик мусора - для циклических ссылок

  • Zend Memory Manager - управление выделением памяти

Как работает refcount

Принцип подсчета ссылок

Каждая переменная в PHP имеет счетчик ссылок, который отслеживает сколько имен переменных указывают на одно значение в памяти.

php

// Пример подсчета ссылок
$a = "hello";  // refcount = 1
$b = $a;       // refcount = 2 (обе переменные указывают на одно значение)
$c = $a;       // refcount = 3

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

Внутреннее представление

c

// Упрощенная структура zval (внутреннее представление переменной)
struct _zval_struct {
    zend_value value;
    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;     // для генерации ошибок
        uint32_t num_args;   // для аргументов функций
        uint32_t fe_pos;     // для итераторов
        uint32_t fe_iter_idx;// для итераторов
    } u2;
    // refcount хранится в value
};

Проблема циклических ссылок

Пример циклической ссылки

php

class Node {
    public $next;
}

$a = new Node();
$b = new Node();

$a->next = $b;  // $a ссылается на $b
$b->next = $a;  // $b ссылается на $a - циклическая ссылка

unset($a);
unset($b);

// Память не освобождается, т.к. refcount каждого объекта = 1
// Они ссылаются друг на друга, но нет внешних ссылок

Циклический сборщик мусора

Алгоритм работы

  1. Обнаружение корней - глобальные переменные, активные символы

  2. Поиск достижимых объектов - обход графа ссылок

  3. Помечение недостижимых - циклические ссылки без внешних связей

  4. Очистка - освобождение памяти

Конфигурация сборщика мусора

ini

; Включение циклического сборщика мусора
zend.enable_gc=1

; Запуск сборщика при каждом цикле
gc_enable();

; Принудительный запуск сборщика
gc_collect_cycles();

Мониторинг работы сборщика мусора

Получение статистики

php

// Включение сбора статистики
gc_enable();

// Выполнение кода...
$node1 = new stdClass();
$node2 = new stdClass();
$node1->next = $node2;
$node2->next = $node1;

unset($node1, $node2);

// Принудительный сбор и получение статистики
$collected = gc_collect_cycles();

echo "Собрано циклов: $collected\n";
echo "Статус GC: " . (gc_enabled() ? 'включен' : 'выключен') . "\n";

Практические аспекты

Когда сборщик мусора запускается

  • Автоматически при достижении порога памяти

  • При вызове gc_collect_cycles()

  • В конце выполнения скрипта

Оптимизация использования памяти

php

// Хорошая практика - явное освобождение больших структур
function processLargeData() {
    $data = getVeryLargeDataSet(); // refcount = 1
    
    process($data);
    
    // Явное освобождение памяти
    unset($data);
    
    // Принудительный сбор, если нужно
    if (memory_get_usage() > 100 * 1024 * 1024) {
        gc_collect_cycles();
    }
}

Сравнение с другими языками

PHP vs Java/C#

  • PHP: преимущественно refcount + циклический GC

  • Java/C#: tracing GC (mark and sweep)

  • PHP: более предскатуемое освобождение памяти

Вывод: PHP использует гибридную систему управления памятью: быстрый подсчет ссылок для большинства случаев и циклический сборщик мусора для сложных структур. Это обеспечивает эффективное использование памяти с минимальными паузами, характерными для полного сборщика мусора.

  • Аватар

    PHP Guru

    Mikhail Savin

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.

Уровень

  • Рейтинг:

    4

  • Сложность:

    8

Навыки

  • PHP

    PHP

Ключевые слова

#garbage

#collection

Подпишись на PHP Developer в телеграм

  • Аватар

    PHP Guru

    Mikhail Savin

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.