Tracemalloc Python: группировка выделений памяти по стеку вызовов

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

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

Разметка прироста памяти

Потоковый синтаксический анализатор разбирает текстовые пакеты и формирует токены с помощью общей вспомогательной функции. К ней обращаются разные прикладные ветки: парсер заголовков, парсер тела и парсер метаданных. Чтобы отслеживать расход памяти, система ведёт диагностику с глубиной стека больше единицы: для каждого выделения фиксируется цепочка кадров tracemalloc.Frame. Однако сами эти кадры хранят только имя файла и номер строки, поэтому сопоставить системные замеры с архитектурой программы можно лишь по заранее заданной карте ответственности — таблице соответствия пар (filename, lineno) текстовым меткам контекстов.

Инспектор памяти отбирает записи StatisticDiff со строгим положительным приростом (size_diff > 0) и раскручивает цепочку кадров от точки аллокации вверх к вызывающим функциям. Поиск продолжается до первого совпадения кадра с картой ответственности. Если совпадение найдено, весь прирост памяти из этой записи начисляется указанному контексту; если же ни один кадр трассировки не попал в карту, запись относится к категории неразмеченных аллокаций.

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

Что уже дано

При выполнении кода доступны вспомогательные функции make_attribution_probe, make_attribution_example и observe_attribution_case, генерирующие реальные объекты tracemalloc.StatisticDiff и карту кадров. В редакторе требуется реализовать только саму функцию attribute_allocations.

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

Реализуйте функцию attribute_allocations(differences, responsibility).

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

  • differences — список объектов tracemalloc.StatisticDiff (от 0 до 2000 записей со значениями size_diff по модулю до 10 000 000 байт и глубиной трассировки от 1 до 16 кадров);
  • responsibility — словарь, сопоставляющий пары (filename, lineno) строковым меткам контекстов длиной от 1 до 64 символов (от 0 до 100 кадров). Несколько кадров могут ссылаться на одну и ту же метку.

Правила агрегации:

  • Учитываются только записи со строгим положительным приростом (size_diff > 0). Записи с нулевым или отрицательным size_diff полностью игнорируются.
  • Для каждой подходящей записи обход кадров выполняется по цепочке трассировки item.traceback от места непосредственного выделения вверх к вызывающему коду. Весь объём size_diff приписывается первой встретившейся в responsibility паре (frame.filename, frame.lineno).
  • Если ни один кадр трассировки не найден в responsibility, значение size_diff добавляется к категории неразмеченной памяти unmarked.
  • Значения size_diff повторных аллокаций и цепочек суммируются для соответствующих контекстов.

Функция возвращает словарь ровно с тремя ключами:

  • "totals" — словарь dict[str, int], содержащий ключи для абсолютно всех уникальных меток из responsibility. Если для контекста не было подходящих аллокаций, его сумма равна 0;
  • "unmarked" — целое число (int), суммарный объём положительного прироста памяти записей, у которых ни один кадр не совпал с картой ответственности;
  • "leader" — любая метка контекста из responsibility с максимальным значением в totals (при равенстве максимумов допустима любая из лидирующих меток). Значение равно None строго тогда, когда в responsibility нет ни одной метки. Категория unmarked в определении лидера не участвует.

Ввод и вывод

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

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

differences, responsibility = make_attribution_example()
report = attribute_allocations(differences, responsibility)
print(report['leader'])
print(report['unmarked'])

Вывод:

headers
0
РешениеPython

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

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

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