Brug disse tips til at analysere din kode og finde ud af, hvor den er mest eller mindst effektiv.

Da "der er mere end én måde at gøre det på" i Python, kan det være en udfordring at finde den mest hukommelseseffektive tilgang til nogle opgaver. Det er her en hukommelsesprofiler kan hjælpe. Ud over at spore lækager hjælper estimering af din kodes hukommelsesprofil med at bestemme, hvilken kode der er hukommelseseffektiv.

Uanset om du udvikler en maskinlæringsmodel eller et websted med Python, kan du estimere hukommelsesprofilen for scripts, individuelle kodelinjer eller funktioner.

Det kan være upraktisk at estimere hukommelsesprofilen for hele din kodebase, da dette kan bremse din applikation betydeligt. Det er bedst, at du selektivt profilerer funktioner eller metoder, som du har mistanke om, bruger mere hukommelse i stedet for. Men selvom du ønsker at gøre dette for hele din applikation, vil du måske dedikere et isoleret modul til at håndtere det.

Der er mange profileringsbiblioteker i Python. Nogle af de mest populære er

instagram viewer
memory_profiler, psutil, Tracemalloc, og pympler. Denne tutorial bruger memory_profiler og psutil.

Mens psutil er ideel til at estimere det samlede hukommelsesforbrug for en metode eller funktionsudførelse, memory_profiler giver mere detaljerede oplysninger om hukommelsesbrug, herunder linje-for-vis og funktionelt niveau brugstendenser over tid.

For at starte skal du installere memory_profiler ind i dit virtuelle Python-miljø. Dette installerer også psutil.

pip installer memory_profiler

Få størrelsen af ​​et objekt i hukommelsen

Du kan starte din hukommelsesprofilering ved først at beregne størrelsen af ​​et objekt, du har til hensigt at bruge i hukommelsen.

Denne type profilering er nyttig i begyndelsen af ​​udviklingen - mens man forsøger at bestemme, hvilken objekttype der skal bruges i et program.

For eksempel, hvis du går i stå med at beslutte, hvilke metoder du skal bruge til at udføre en opgave, f.eks. Python-datatype, kan du få størrelsen af ​​hver i bytes for at bestemme, hvilken der er mere let til dit brug sag.

Det sys.getsizeof indbygget metode er praktisk her:

importere sys
Print(f" listestørrelse: {sys.getsizeof([])} bytes")
Print(f"ordbog størrelse: {sys.getsizeof (dict)} bytes")
Print(f"tuple størrelse: {sys.getsizeof(())} bytes")
Print(f" sæt størrelse: {sys.getsizeof({})} bytes")

Her er outputtet:

Du kan også bruge sys.getsizeof metode til at sammenligne hukommelsesstørrelsen for en indbygget og brugerdefineret funktion.

For eksempel, sammenligne denne brugerdefinerede længde funktion at bruger en Python til loop med det indbyggede len fungere:

importere sys

defgetLængde(gentagelig):
tælle = 0

til jeg i iterable:
tælle +=1

Vend tilbage tælle

Print(f" Indbygget længde funktion: {sys.getsizeof (len)} bytes")
Print(f"Brugerdefineret længde funktion: {sys.getsizeof (getLength)} bytes")

Ovenstående kode giver følgende output:

Dog mens sys.getsizeof måler et objekts størrelse i hukommelsen, tager det kun højde for selve objektet og ikke dem, der refererer til det. Til det har du brug for en mere detaljeret profileringsmetode.

Find hukommelsesprofilen for en Python-funktion

Du kan få en mere detaljeret hukommelsesprofil for hver kodelinje i en funktion ved hjælp af memory_profiler pakke. Dette indebærer tilføjelse af @profil dekoratør til din funktion eller metode:

importere pandaer
import numpy
fra memory_profiler import profil

klasse Manipuler:
@profil
def manipulateData (selv):
df = pandaer. DataFrame({
'A' :[0, 3, numpy.nan, 10, 3, numpy.nan],
'B': [numpy.nan, "Pandas", numpy.nan, "Pandas", "Python", "JavaScript"],
})

df.fillna (method='bfill', inplace=True)
df.fillna (method='ffill', inplace=True)
retur str (df)

manip = Manipuler()
print (manip.manipulateData())

Ovenstående kode giver en detaljeret hukommelsesprofil for hver linje kode i funktionen som vist:

Det Mem brug kolonne angiver hukommelsesforbruget for en bestemt kodelinje, mens Forøgelse kolonne viser de overhead, som hver linje bidrager med. Det Hændelse kolonne definerer antallet af gange en kodelinje tildeler eller deallokerer hukommelse.

For eksempel, i ovenstående output, forekom linje 11 to gange med et hukommelsestilvækst på 0,1 MiB (Mebibyte), hvilket øgede hukommelsesforbruget til 55,4 MiB. Linje 19 og 22 bidrog også med henholdsvis 0,2 MiB og 0,3 MiB, hvilket samlede hukommelsesforbruget til 55,9 MiB.

Find hukommelsesprofilen for et Python-script efter tidsstempel

Du kan også estimere hukommelsesprofilen for et helt Python-script ved hjælp af memory_profiler ved at køre mprof kommando i terminalen som vist:

mpof køre script_name.py

Ovenstående kommando prøver det angivne script hver 0.1s og opretter automatisk en .dat fil i din nuværende projektmappe.

Tallene, der følger MEM notation er hukommelsesbrugsprofilerne for Python-scriptet ved et bestemt tidsinterval. De sidste tal til højre repræsenterer tidsstemplet, som profileringsmaskinen fangede for hver hukommelsesbrug.

Du kan også få et plot af hukommelsesprofilen. Dette kræver en installation af matplotlib:

pip installer matplotlib

Når det er installeret, skal du køre mprof kommando som sådan:

mpr plot

Her er outputtet i dette tilfælde:

Kør scripthukommelsesprofilen i en dedikeret Python-fil

Du vil måske profilere for forskellige Python-scripts. Du kan gøre det ved hjælp af et dedikeret Python-modul via Python's delproces.

På denne måde kan du adskille din hukommelsesprofiler fra din kodebase og gemme grafoutputtet lokalt:

importere delproces

subprocess.run([
'mprof', 'løb', '--inkluder-børn', 'missing.py'
])

# gem plotoutputtet lokalt
subprocess.run(['mprof', 'grund', '--output=output.jpg'])

For at køre scriptets hukommelsesprofil behøver du kun at køre Python-filen, der indeholder ovenstående kode. Dette genererer et hukommelsesprofilplot (output.jpg) i filbiblioteket:

Find mængden af ​​brugt hukommelse fra en funktionsudførelse

Du kan finde den samlede hukommelsesprofil for en metode eller funktion under udførelse ved hjælp af psutil pakke.

For eksempel for at profilere det foregående Pandas DataFrame manipulation metode inde i en anden Python-fil:

importere psutil
importere sys
importere os
sys.path.append (sys.path[0] + "/..")

# importer klassen, der indeholder din metode
fra en eller anden kode.mangler importere Manipulere

# instantiér klassen
manip = Manipuler()

proces = psutil. Process (os.getpid())
initial_memory = process.memory_info().rss

# kør målmetoden:
manip.manipulateData()

# få hukommelsesoplysningerne efter udførelse
final_memory = process.memory_info().rss
memory_consumed = final_memory - initial_memory
memory_consumed_mb = memory_consumed / (1024 * 1024)
Print(f"Hukommelse forbrugt af funktionen: {memory_consumed_mb:.2f} MB")

Ovenstående estimerer metodens samlede hukommelsesprofil i megabyte (MB) som vist:

Find hukommelsesprofilen for en kodelinje i Jupyter Notebook

Hvis du bruger iPython i Jupyter Notebook, kan du beregne hukommelsesprofilen for en one-liner vha. memory_profiler. Du skal kun indlæse memory_profiler i én celle. Tilsæt derefter %memit magisk funktion til din kode i efterfølgende celler; dette returnerer kodens maksimale hukommelse og øgede størrelse.

Denne metode virker ikke med almindelige Python-scripts udover iPython i Jupyter Notebook.

For eksempel:

Du kan også bruge %memit magisk funktion i Jypyter Notebook til at profilere en funktions hukommelse under kørsel:

Forbedre din hukommelseseffektivitet i din Python-kode

I betragtning af de tunge dataløftningsopgaver, vi ofte bruger Python til, har hver kodelinje brug for tilstrækkelig optimering for at administrere hukommelsesforbrug. Mens Python har mange indbyggede Python-funktioner, resulterer ikke-refererede objekter i hukommelseslækager.

Hvis du har droppet enhver Python-syntaks, der fungerer i din kodebase uden at overveje hukommelsesbrug, vil du måske se tilbage, før du går for langt.