Освобождает ли сборщик мусора память обратно операционной системе
Что проверяют
Понимаете ли вы, что в CPython работают два независимых механизма и что между освобождением объекта и возвратом страниц операционной системе стоит собственный распределитель памяти. Практический смысл вопроса обычно такой: почему потребление процесса не падает после обработки большого файла.
Как отвечать
Объект уничтожается, как только счётчик ссылок падает до нуля, немедленно и без всякого сборщика. Модуль gc занимается только циклическими ссылками, до которых подсчёт не добирается, и gc.collect() собирает именно их.
Дальше начинается слой распределителя. Мелкие объекты живут в пулах внутри арен, а арену Python берёт у системы. Вернуть её можно, только когда она полностью пуста, и один выживший объект удерживает всю арену. Отсюда типичная картина: словарь на миллион записей удалён, а потребление почти не изменилось. Крупные блоки идут мимо этого механизма в системный распределитель, и вернёт он их сразу или придержит, решает уже он.
Плюс есть память, которая не освобождается по смыслу: интернированные строки, объекты типов и модулей, внутренние кэши и свободные списки интерпретатора.
Практический вывод стоит проговорить: если пик разовый, выносите работу в отдельный процесс и завершайте его, либо обрабатывайте данные потоком, а не собирайте всё в список. Управлять возвратом памяти из кода не получится.
Где спотыкаются
Считают сборщиком мусора только модуль gc и уверены, что без явного вызова ничего не освобождается. Основную работу делает подсчёт ссылок, а gc.disable() в горячем коде отключает лишь сбор циклов, а не освобождение памяти вообще.
Думают, что del x освобождает память. Он убирает имя и уменьшает счётчик на единицу. Если на объект ссылается список, замыкание, кэш или трассировка пойманного исключения, объект остаётся жив, и профиль это покажет.
Ищут утечку по потреблению процесса. Оно не падает из-за фрагментации арен даже там, где утечки нет. Смотреть надо на число живых объектов через tracemalloc и на динамику от прогона к прогону: настоящая утечка растёт монотонно, фрагментация выходит на полку.