Утечка памяти Python: найдите буфер, удерживающий объекты

Напишите решение на Python и проверьте его на странице.

Другие упражнения по этой теме: Память Python: задачи на tracemalloc, утечки и slots.

Локализация удерживающего буфера

Фоновый конвейер принимает партии сообщений, преобразует их в рабочие структуры данных и перекладывает результат в целевую очередь. Стенд работает без видимых сбоев, но в процессе непрерывной обработки потребление памяти монотонно возрастает. Профилирование с помощью tracemalloc точно указывает на строку внутри функции трансформации, где создаются проблемные объекты. При этом сама функция чиста: порождённые ею экземпляры не задерживаются локально, а незаметно оседают в одном из глобальных буферов — кэше дедупликации, отладочном журнале ошибок, очереди повторов или реестре сессий.

Чтобы выяснить, какая именно коллекция удерживает лишние данные, исследовательская утилита поочерёдно очищает подозрительные структуры. После каждого такого действия инструмент делает контрольный снимок памяти и сопоставляет освобождённый объём с исходной строкой аллокации.

Определите имя удерживающего контейнера, очистка которого привела к реальному освобождению памяти, выделенной проблемной строкой.

Что уже дано

В редакторе представлена сигнатура функции find_retaining_container(containers, allocation_site).

При выполнении кода доступны вспомогательные инструменты:

  • make_retention_probe(names, owner, ...) — готовит испытательный стенд с реальными буферами под управлением tracemalloc;
  • observe_retention_probe(probe) — запускает диагностику и возвращает отчёт с контрольными снимками;
  • make_retention_example() — создаёт готовый типовой сценарий.

Служебный параметр owner используется только стендом для наполнения буферов и в диагностическую функцию не передаётся. Реализовывать эти вспомогательные функции самостоятельно не требуется.

Что нужно сделать

Реализуйте функцию find_retaining_container(containers, allocation_site).

Функция принимает два аргумента:

  • containers — отображение (dict или аналогичный mapping), сопоставляющее строковые имена буферов с 2–6 изменяемыми коллекциями (list, dict или их стандартные подклассы). В каждом заполненном буфере находится от 2 до 16 объектов размером от 64 до 8192 байт (отвлекающие аллокации в других буферах могут быть до 8 раз крупнее);
  • allocation_site — кортеж вида (filename, lineno), где filename (str) — имя файла, а lineno (int) — положительный номер строки, в которой фактически происходило выделение памяти под проблемные объекты.

Требования к поведению:

  • Выполните серию контрольных экспериментов: очищайте проверяемые коллекции по отдельности и фиксируйте реальное изменение занятой памяти через контрольные снимки tracemalloc.take_snapshot().
  • Определите буфер, освобождение которого приводит к фактическому уменьшению объёма памяти, аллоцированной в точке allocation_site.
  • Функция должна вернуть имя удерживающего контейнера в виде строки (str или совместимого строкового типа).
  • Не требуется вычислять процентные доли, абсолютные пороги байтов, оценивать системный RSS процесса или восстанавливать очищенные коллекции после проведения замеров.

Ввод и вывод

Стандартные потоки ввода stdin и вывода stdout в решении не используются: считывать ввод и вызывать print() не нужно. После выполнения кода учащегося проверяющая система считывает из пространства имён модуля функцию верхнего уровня find_retaining_container и вызывает её с проверочными аргументами.

Пример использования

names = ('dedup_cache', 'error_log', 'retries')
for owner in ('dedup_cache', 'error_log'):
    probe = make_retention_probe(names, owner)
    observed = observe_retention_probe(probe)
    print(observed['result'])

Вывод:

dedup_cache
error_log
РешениеPython

Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.

Отправьте решение, чтобы увидеть результаты тестов.

Связанные задачи