В приложении RSS процесса растёт, но снимки tracemalloc почти не меняются: какой механизм это объясняет?
tracemalloc отслеживает не весь объём памяти процесса, а только трассируемые блоки памяти, выделенные через поддерживаемые Python-аллокаторы. Поэтому рост RSS при почти неизменном tracemalloc обычно означает, что память выделяется нативным кодом, через неотслеживаемый malloc или mmap, либо расходуется самим аллокатором и библиотечными кэшами.
Эти метрики отвечают на разные вопросы: tracemalloc помогает найти источники Python-аллокаций, а RSS показывает, сколько страниц процесса фактически находится в оперативной памяти. Для диагностики утечки их нужно сопоставлять, а не считать взаимозаменяемыми.
Управление памятью в Python скрывает детали выделения объектов от разработчика. Для поиска источников роста Python-объектов в стандартную библиотеку добавили tracemalloc: он сохраняет трассировки мест, где выделялись отслеживаемые блоки, и позволяет сравнивать снимки.
Однако процесс Python часто использует библиотеки на C, например обработчики изображений, численные библиотеки или драйверы. Такой код может выделять большие буферы напрямую через системный аллокатор или отображение файлов в память, поэтому одного инструмента, ориентированного на Python-аллокации, недостаточно для анализа всего адресного пространства.
Предположим, сервис принимает данные, создаёт временные объекты Python и передаёт их библиотеке на C. Через несколько часов RSS увеличивается на гигабайты, но число живых Python-объектов и объём, показанный tracemalloc, остаются примерно постоянными.
Если ошибочно считать tracemalloc полным профилировщиком памяти, можно начать искать несуществующую утечку в Python-коде. В результате будут потрачены ресурсы на оптимизацию незначительных объектов, тогда как проблема может находиться в нативном буфере, кэше библиотеки, фрагментации аллокатора или отображённых страницах.
RSS — это объём страниц процесса, резидентных в физической памяти в данный момент. Он зависит не только от живых Python-объектов, но и от нативных выделений, загруженных библиотек, отображений файлов, страниц стеков, копирования при записи и поведения системного аллокатора.
tracemalloc собирает информацию о трассируемых блоках и связывает их с местами выделения в Python-коде. Он полезен для ответа на вопрос «какие участки Python-программы удерживают или создают больше отслеживаемой памяти», но не обязан отражать произвольные вызовы malloc, mmap и внутренние хранилища сторонних C-библиотек.
Возможны несколько причин расхождения:
mmap или файл и учитывается в RSS, но не представлена как обычная Python-аллокация;Диагностика должна начинаться с одновременной фиксации RSS, снимков tracemalloc и характера нагрузки. Если RSS растёт вместе с tracemalloc, сначала анализируют Python-трассировки и время жизни объектов. Если RSS растёт отдельно, подключают инструменты нативного профилирования, проверяют кэши библиотек и анализируют отображения процесса.
У tracemalloc есть цена: хранение трассировок увеличивает потребление памяти и может влиять на производительность. Поэтому его обычно включают в воспроизводимом тесте или на ограниченный период, а не безусловно оставляют в высоконагруженном production-процессе.
Сервис преобразования изображений после каждой операции освобождал Python-объекты, но RSS постепенно рос. Снимки tracemalloc показывали небольшой стабильный объём, а профилирование времени выполнения указывало на нативную библиотеку обработки изображений.
Рассматривались варианты:
Выбрали последний вариант и дополнительно ограничили размер рабочих пакетов. Профилирование показало, что библиотека сохраняла буферы для повторного использования; после настройки её кэша RSS перестал расти без необходимости увеличивать сборку мусора или переписывать Python-код.
Нет. Это означает только отсутствие заметного роста среди отслеживаемых им блоков. Утечка может находиться в нативном расширении, в буферах библиотеки, в отображениях памяти или в ресурсах, которые не представлены обычными Python-объектами. Для вывода об отсутствии утечки нужно сопоставить Python-профилирование с RSS и, при необходимости, нативным инструментом.
Освобождение памяти приложением не гарантирует немедленного возврата страниц операционной системе. Аллокатор может оставить их в своих аренах для будущих выделений, а часть страниц может быть фрагментирована и непригодна для возврата целиком. Поэтому уменьшение числа живых объектов или завершение операции не обязано сопровождаться таким же уменьшением RSS.
Нет. Нужно сравнивать динамику на одинаковых этапах нагрузки и учитывать момент запуска tracemalloc. Полезно разделять базовый размер процесса, память после прогрева, память после серии операций и память после стабилизации; иначе однократный кэш, загруженная библиотека или изменение рабочей нагрузки можно ошибочно принять за утечку.