Използвайте тези съвети, за да анализирате кода си и да откриете къде е най- или най-малко ефективен.
Тъй като „има повече от един начин да го направите“ в Python, намирането на най-ефективния от паметта подход за някои задачи може да бъде предизвикателство. Това е мястото, където профилът на паметта може да помогне. Освен проследяването на течове, оценката на профила на паметта на вашия код помага да се определи кой код е ефективен по отношение на паметта.
Независимо дали разработвате модел за машинно обучение или уебсайт с Python, можете да оцените профила на паметта за скриптове, отделни кодови редове или функции.
Оценяването на профила на паметта на цялата ви кодова база може да е непрактично, тъй като това може значително да забави вашето приложение. Най-добре е вместо това избирателно да профилирате функции или методи, които подозирате, че може да консумират повече памет. Но дори ако искате да направите това за цялото си приложение, може да искате да посветите изолиран модул, който да го обработва.
В Python има много библиотеки за профилиране. Някои от най-популярните са memory_profiler, psutil, Tracemalloc, и пимплер. Този урок използва memory_profiler и psutil.
Докато psutil е идеален за оценка на общата консумация на памет за изпълнение на метод или функция, memory_profiler дава по-подробна информация за използването на паметта, включително тенденции за използване ред по и функционално ниво във времето.
За да започнете, инсталирайте memory_profiler във вашата виртуална среда на Python. Това също се инсталира psutil.
pip инсталирате memory_profiler
Вземете размера на обект в паметта
Можете да започнете профилирането на паметта си, като първо изчислите размера на обект, който възнамерявате да използвате в паметта.
Този тип профилиране е полезно в началото на разработката - докато се опитвате да определите кой тип обект да използвате в програма.
Например, ако се затрудните да решите кои методи да използвате за постигане на дадена задача, да речем подходящия Тип данни на Python, можете да получите размера на всеки в байтове, за да определите кой е по-лек за вашата употреба случай.
The sys.getsizeof вграденият метод е полезен тук:
импортиране система
печат (f"размер на списъка: {sys.getsizeof([])} байтове")
печат (f"размер на речника: {sys.getsizeof (dict)} байтове")
печат (f"размер на кортежа: {sys.getsizeof(())} байтове")
печат (f"зададен размер: {sys.getsizeof({})} байта")
Ето изхода:
Можете също да използвате sys.getsizeof метод за сравняване на размера на паметта на вградена и потребителска функция.
Например, сравнете тази персонализирана функция за дължина, която използва Python for цикъл с вградения len функция:
импортиране система
дефgetLength(повтарящ се):
брои = 0за аз в итерируем:
брои +=1връщане броя
печат (f"Вградена функция за дължина: {sys.getsizeof (len)} байтове")
печат (f"Функция за персонализирана дължина: {sys.getsizeof (getLength)} байтове")
Горният код дава следния резултат:
Въпреки това, докато sys.getsizeof измерва размера на обект в паметта, той отчита само самия обект, а не тези, които го препращат. За целта ще ви трябва по-подробен метод за профилиране.
Намерете профила на паметта на функция на Python
Можете да получите по-подробен профил на паметта на всеки кодов ред на функция, като използвате memory_profiler пакет. Това включва добавяне на @профил декоратор към вашата функция или метод:
вносни панди
импортиране на numpy
от профил за импортиране на memory_profilerклас Манипулиране:
@профил
def manipulateData (self):
df = панди. DataFrame({
'A': [0, 3, numpy.nan, 10, 3, numpy.nan],
'B': [numpy.nan, "Панди", numpy.nan, "Панди", "Python", "JavaScript"],
})df.fillna (method='bfill', inplace=True)
df.fillna (method='ffill', inplace=True)
връщане str (df)
manip = Манипулиране()
печат (manip.manipulateData())
Горният код дава подробен профил на паметта на всеки ред от код във функцията, както е показано:
The Използване на Mem колоната показва използването на паметта за конкретен кодов ред, докато Увеличаване колоната показва режийните разходи, допринесени от всеки ред. The Възникване колона дефинира броя пъти, когато кодов ред разпределя или освобождава памет.
Например в горния изход ред 11 се появява два пъти с увеличение на паметта от 0,1 MiB (Mebibyte), което увеличава използването на паметта до 55,4 MiB. Редове 19 и 22 също допринесоха съответно с 0,2 MiB и 0,3 MiB, което общо използва паметта до 55,9 MiB.
Намерете профила на паметта на скрипт на Python по времево клеймо
Можете също да оцените профила на паметта на цял скрипт на Python, като използвате memory_profiler като стартирате проф команда в терминала, както е показано:
mprof изпълнете script_name.py
Горната команда взема проби от посочения скрипт на всеки 0,1 секунди и автоматично създава a .dat файл във вашата текуща директория на проекта.
Цифрите, които следват MEM нотация са профилите на използване на паметта на скрипта на Python в определен интервал от време. Последните цифри вдясно представляват клеймото за време, което профайлърът е уловил за всяко използване на паметта.
Можете също така да получите графика на профила на паметта. Това изисква инсталиране на matplotlib:
pip инсталирайте matplotlib
След като го инсталирате, стартирайте проф команда така:
mprof парцел
Ето изхода в този случай:
Стартирайте профила на паметта на скрипта в специален Python файл
Може да искате да направите профил за различни скриптове на Python. Можете да направите това използвайки специален модул на Python чрез Python подпроцес.
По този начин можете да отделите вашия профайлър на паметта от вашата кодова база и да запишете изхода на графиката локално:
импортиране подпроцес
subprocess.run([
'mprof', "бягам", '--include-children', 'missing.py'
])
# запазете резултата от графиката локално
subprocess.run(['mprof', "парцел", '--output=output.jpg'])
За да стартирате профила на паметта на скрипта, трябва само да стартирате Python файла, съдържащ горния код. Това генерира диаграма на профила на паметта (изход.jpg) във файловата директория:
Намерете количеството памет, използвано от изпълнение на функция
Можете да намерите общия профил на паметта на метод или функция по време на изпълнение, като използвате psutil пакет.
Например, за да профилирате предишния Манипулиране на Pandas DataFrame метод в друг файл на Python:
импортиране psutil
импортиране система
импортиране операционна система
sys.path.append (sys.path[0] + "/..")# импортирайте класа, съдържащ вашия метод
от somecode.missing импортиране Манипулирайте# инстанцирайте класа
manip = Манипулиране()процес = psutil. Процес (os.getpid())
първоначална_памет = process.memory_info().rss# изпълнете целевия метод:
manip.manipulateData()
# вземете информация за паметта след изпълнение
final_memory = process.memory_info().rss
консумирана_памет = крайна_памет - първоначална_памет
memory_consumed_mb = memory_consumed / (1024 * 1024)
печат (f"Памет, изразходвана от функцията: {memory_consumed_mb:.2е} MB")
Горното оценява общия профил на паметта на метода в мегабайти (MB), както е показано:
Намерете профила на паметта на кодов ред в Jupyter Notebook
Ако използвате iPython в Jupyter Notebook, можете да изчислите профила на паметта на едноредов, като използвате memory_profiler. Трябва само да заредите memory_profiler в една клетка. След това добавете % memit магическа функция към вашия код в следващите клетки; това връща пиковата памет на кода и увеличения размер.
Този метод не работи с обикновени скриптове на Python освен iPython в Jupyter Notebook.
Например:
Можете също да използвате % memit магическа функция в Jypyter Notebook за профилиране на паметта на функция по време на изпълнение:
Подобрете ефективността на вашата памет във вашия Python код
Имайки предвид тежките задачи за повдигане на данни, за които често използваме Python, всеки кодов ред се нуждае от подходяща оптимизация, за да управлява използването на паметта. Докато Python разполага с много вградени функции на Python, нереферираните обекти водят до изтичане на памет.
Ако сте изпускали всеки синтаксис на Python, който работи във вашата кодова база, без да обмисляте използването на паметта, може да искате да погледнете назад, преди да отидете твърде далеч.