Воспользуйтесь этими советами, чтобы проанализировать свой код и выяснить, где он наиболее или наименее эффективен.

Поскольку в Python «есть несколько способов сделать это», поиск наиболее эффективного с точки зрения использования памяти подхода для некоторых задач может оказаться сложной задачей. Здесь может помочь профилировщик памяти. Помимо отслеживания утечек, оценка профиля памяти вашего кода помогает определить, какой код эффективно использует память.

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

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

instagram viewer

В Python есть много библиотек профилирования. Некоторые из самых популярных memory_profiler, psutil, Трацемаллок, и пимплер. В этом учебнике используется memory_profiler и psutil.

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

Для начала установите memory_profiler в вашу виртуальную среду Python. Это также устанавливает psutil.

pip установить memory_profiler

Получить размер объекта в памяти

Вы можете начать профилирование памяти, сначала вычислив размер объекта, который вы собираетесь использовать в памяти.

Этот тип профилирования полезен в начале разработки — при попытке определить, какой тип объекта использовать в программе.

Например, если вы застряли, решая, какие методы использовать для выполнения задачи, скажем, подходящие Тип данных Python, вы можете получить размер каждого в байтах, чтобы определить, какой из них более легкий для вашего использования. случай.

sys.getsizeof здесь пригодится встроенный метод:

Импортировать система
Распечатать(f"размер списка: {sys.getsizeof([])} байты")
Распечатать(f"размер словаря: {sys.getsizeof (словарь)} байты")
Распечатать(f"размер кортежа: {sys.getsizeof(())} байты")
Распечатать(f"установить размер: {sys.getsizeof({})} байт")

Вот результат:

Вы также можете использовать sys.getsizeof метод для сравнения размера памяти встроенной и пользовательской функции.

Например, сравните эту пользовательскую функцию длины, которая использует цикл Python for со встроенным Лен функция:

Импортировать система

дефполучитьдлину(повторяемый):
количество = 0

для я в повторяемый:
количество +=1

возвращаться считать

Распечатать(f"Встроенная функция длины: {sys.getsizeof (длина)} байты")
Распечатать(f"Пользовательская функция длины: {sys.getsizeof (getLength)} байты")

Приведенный выше код дает следующий результат:

Однако пока sys.getsizeof измеряет размер объекта в памяти, он учитывает только сам объект, а не те, которые на него ссылаются. Для этого вам понадобится более подробный метод профилирования.

Найдите профиль памяти функции Python

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

импортировать панд
импортировать numpy
из профиля импорта memory_profiler

класс Манипулировать:
@профиль
def манипулировать данными (я):
дф = панды. Кадр Данных({
«А»: [0, 3, число.нан, 10, 3, число.нан],
'B': [numpy.nan, "Панды", numpy.nan, "Панды", "Python", "JavaScript"],
})

df.fillna (метод = 'bfill', inplace = True)
df.fillna (метод = 'ffill', inplace = True)
вернуть ул (df)

манипулировать = Манипулировать ()
печать (manip.manipulateData())

Приведенный выше код дает подробный профиль памяти для каждой строки кода в функции, как показано ниже:

Использование памяти столбец показывает использование памяти для конкретной строки кода, в то время как Увеличение столбец показывает накладные расходы, внесенные каждой строкой. Вхождение столбец определяет, сколько раз строка кода выделяет или освобождает память.

Например, в приведенном выше выводе строка 11 встречается два раза с приращением памяти на 0,1 МБ (мебибайт), что увеличивает использование памяти до 55,4 МБ. Строки 19 и 22 также внесли 0,2 МБ и 0,3 МБ соответственно, в результате чего общее использование памяти составило 55,9 МБ.

Найдите профиль памяти скрипта Python по метке времени

Вы также можете оценить профиль памяти всего скрипта Python, используя memory_profiler запустив мпроф команду в терминале, как показано:

mprof запустить script_name.py

Приведенная выше команда отбирает указанный скрипт каждые 0,1 с и автоматически создает .dat внутри вашего текущего каталога проекта.

Цифры, следующие за МЕМ нотация — это профили использования памяти сценария Python в определенный интервал времени. Последние цифры справа представляют временную метку, полученную профилировщиком для каждого использования памяти.

Вы также можете получить график профиля памяти. Для этого требуется установка matplotlib:

pip установить matplotlib

После установки запустите мпроф команда так:

участок

Вот вывод в этом случае:

Запустите профиль памяти сценария в выделенном файле Python

Возможно, вы захотите профилировать разные скрипты Python. Вы можете сделать это используя специальный модуль Python через Python подпроцесс.

Таким образом, вы можете отделить профилировщик памяти от базы кода и локально сохранить вывод графа:

Импортировать подпроцесс

subprocess.run([
'мпроф', 'бегать', '--включить-детей', 'отсутствует.py'
])

# сохранить вывод графика локально
subprocess.run(['мпроф', 'сюжет', '--output=output.jpg'])

Чтобы запустить профиль памяти сценария, вам нужно всего лишь запустить файл Python, содержащий приведенный выше код. Это генерирует график профиля памяти (вывод.jpg) в каталоге файлов:

Найдите объем памяти, используемый при выполнении функции

Вы можете найти общий профиль памяти метода или функции во время выполнения, используя psutil упаковка.

Например, чтобы профилировать предыдущий Манипуляции Pandas DataFrame внутри другого файла Python:

Импортировать psutil
Импортировать система
Импортировать Операционные системы
sys.path.append (sys.path[0] + "/..")

# импортируем класс, содержащий ваш метод
от какой-то код. отсутствует Импортировать Манипулировать

# создать экземпляр класса
манипулировать = Манипулировать ()

процесс = psutil. Процесс (os.getpid())
Initial_memory = процесс.memory_info().rss

# запускаем целевой метод:
manip.manipulateData()

# получить информацию о памяти после выполнения
final_memory = процесс.memory_info().rss
memory_consumed = конечная_память - начальная_память
memory_consumed_mb = memory_consumed / (1024 * 1024)
Распечатать(f"Память, потребляемая функцией: {memory_consumed_mb:.2ж} МБ")

Приведенное выше оценивает общий профиль памяти метода в мегабайтах (МБ), как показано:

Найдите профиль памяти строки кода в Jupyter Notebook

Если вы используете iPython в Jupyter Notebook, вы можете рассчитать профиль памяти однострочного приложения, используя memory_profiler. Вам нужно только загрузить memory_profiler в одной клетке. Затем добавьте %memit волшебная функция для вашего кода в последующих ячейках; это возвращает пиковую память кода и увеличенный размер.

Этот метод не работает с обычными скриптами Python, кроме iPython в Jupyter Notebook.

Например:

Вы также можете использовать %memit magic function в Jypyter Notebook для профилирования памяти функции во время выполнения:

Повысьте эффективность использования памяти в коде Python

Учитывая сложные задачи по подъему данных, для которых мы часто используем Python, каждая строка кода нуждается в адекватной оптимизации для управления использованием памяти. Хотя в Python имеется множество встроенных функций Python, объекты без ссылок приводят к утечкам памяти.

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