Programmering

Hvordan bruke cProfile for å profilere Python-kode

Python er kanskje ikke det raskeste språket, men det er ofte raskt nok. Og Python er ideelt når programmererens tid betyr mer enn CPU-tid.

Når det er sagt, hvis en gitt Python-app er laggy, er du ikke forpliktet til å bare suge den opp. Verktøy som følger med lagerinstallasjonen av Python-tolken kan gi deg detaljert tilbakemelding om hvilke deler av programmet som er treg, og gi noen tips om hvordan du kan øke hastigheten på dem.

Hvordan bruke cProfile

De cProfil modulen samler statistikk om kjøringstiden til et Python-program. Den kan rapportere om alt fra hele appen til et enkelt utsagn eller uttrykk.

Her er et leketøyeksempel på hvordan du bruker cProfil:

def add (x, y): x + = str (y) return x def add_2 (x, y): hvis y% 20000 == 0: z = [] for q i området (0,400000): z.append ( q) def main (): a = [] for n i området (0,200000): add (a, n) add_2 (a, n) if __name__ == '__main__': import cProfile cProfile.run ('main ( ) ') 

Dette eksemplet kjører applikasjonens hoved() funksjon og analyserer ytelsen til hoved() og alt hoved() ringer. Det er også mulig å analysere bare adel av et program, men den vanligste bruken for det første er å profilere hele programmet.

Kjør eksemplet ovenfor, og du vil bli møtt med noe som følgende utgang:

Det som vises her er en liste over alle funksjonsanropene som er gjort av programmet, sammen med statistikk om hver:

  • Øverst (første linje i blått) ser vi det totale antallet anrop som er gjort i det profilerte programmet og den totale gjennomføringstiden. Du kan også se en figur for "primitive samtaler", som betyr ikke-rekursiv samtaler eller anrop direkte til en funksjon som ikke i sin tur kaller seg lenger nede i samtalestakken.
  • ncalls: Antall anrop. Hvis du ser to tall atskilt med en skråstrek, er det andre tallet antallet primitive anrop for den funksjonen.
  • heltid: Total tid brukt i funksjonen, ikke inkludert samtaler til andre funksjoner.
  • percall: Gjennomsnittlig tid per samtale for heltid, avledet ved å ta heltid og dele den med ncalls.
  • cumtime: Total tid brukt i funksjonen, inkludert samtaler til andre funksjoner.
  • percall (Nr. 2): Gjennomsnittlig tid per samtale for cumtime (cumtime delt på ncalls).
  • filnavn: lineno: Filnavnet, linjenummeret og funksjonsnavnet for den aktuelle samtalen.

Slik endrer du cProfile-rapporter

Som standard, cProfil sorterer utdataene etter "standardnavn", noe som betyr at den sorterer etter teksten i kolonnen lengst til høyre (filnavn, linjenummer osv.).

Standardformatet er nyttig hvis du vil ha en generell rapport ovenfra og ned av hver enkelt funksjon som kalles for referanse. Men hvis du prøver å komme til bunns i en flaskehals, vil du sannsynligvis ha de mest tidkrevende delene av programmet først.

Vi kan produsere disse resultatene ved å påkallecProfil litt annerledes. Legg merke til hvordan den nederste delen av programmet ovenfor kan bearbeides for å sortere statistikken etter en annen kolonne (i dette tilfellet ncalls):

hvis __name__ == '__main__': import cProfile, pstats profiler = cProfile.Profile () profiler.enable () main () profiler.disable () stats = pstats.Stats (profiler) .sort_stats ('ncalls') stats.print_stats () 

Resultatene vil se ut slik:

Slik fungerer alt dette:

  • I stedet for å utføre en kommando i form av cProfile.run (), som ikke er veldig fleksibel, lager vi en profilering gjenstand, profiler.
  • Når vi vil profilere noe, ringer vi først .muliggjøre() på profilerobjektforekomsten, kjør deretter handlingen, og ring deretter .disable (). (Dette er en måte å bare profilere en del av et program på.)
  • De pstats modulen brukes til å manipulere resultatene som er samlet inn av profilobjektet og skrive ut resultatene.

Kombinere et profilobjekt og pstats lar oss manipulere fangede profildata - for eksempel å sortere generert statistikk på en annen måte. I dette eksemplet bruker .sort_stats ('ncalls') sorterer statistikken etter ncalls kolonne. Andre sorteringsalternativer er tilgjengelige.

Hvordan bruke cProfile-resultater for optimalisering

Sorteringsalternativene som er tilgjengelige for cProfil output gir oss muligheten til å plage ut potensielle ytelsesflaskehalser i et program.

ncalls

Den første og viktigste informasjonen du kan finne ut av cProfil er hvilke funksjoner som ofte kalles, ved hjelp av ncalls kolonne.

I Python pådrar det seg bare å utføre et funksjonsanrop relativt mye overhead. Hvis noen funksjoner kalles gjentatte ganger i en tett løkke, selv om det ikke er en langvarig funksjon, vil det garantert påvirke ytelsen.

I eksemplet ovenfor funksjonen legge til (og funksjonen add_2) kalles gjentatte ganger i en løkke. Flytter løkken inn i legge til funksjonen i seg selv, eller inline legge til fungerer helt, vil løse dette problemet.

heltid

En annen nyttig statistikk som funksjoner programmet bruker mesteparten av tiden på å utføre, i form av heltid kolonne.

I eksemplet ovenfor er add_2 funksjonen bruker en sløyfe for å simulere noen dyre beregninger, som skyver dens heltid scorer til toppen. Enhver funksjon med høy heltid score fortjener en nøye titt, spesielt hvis den kalles mange ganger eller i en tett løkke.

Merk at du alltid må vurdere kontekst der funksjonen brukes. Hvis en funksjon har en høy heltid men kalles bare én gang - for eksempel bare når programmet starter - det er mindre sannsynlig å være en flaskehals. Men hvis du prøver å redusere oppstartstiden, vil du vite om en funksjon som kalles ved oppstart, får alt annet til å vente.

Hvordan eksportere cProfile data

Hvis du vil bruke cProfilgenerert statistikk på mer avanserte måter, kan du eksportere dem til en datafil:

stats = pstats.Stats (profiler) stats.dump_stats ('/ path / to / stats_file.dat') 

Denne filen kan leses inn igjen ved å bruke pstats modul, deretter sortert eller vist med pstats. Dataene kan også brukes på nytt av andre programmer. To eksempler:

  • pyprof2calltree gjengir detaljerte visualiseringer av programmets samtalediagram og bruksstatistikk fra profildata. Denne artikkelen gir et detaljert eksempel fra bruken av den virkelige verden.
  • snakeviz genererer også visualiseringer fra cProfil data, men bruker en annen representasjon for dataene - en "sunburst" i stedet for pyprof2calltree's "flamme" -graf.

Utover cProfile for Python-profilering

cProfil er neppe den eneste måten å profilere et Python-program på. cProfil er absolutt en av de mest praktiske måtene, gitt at den følger med Python. Men andre fortjener oppmerksomhet.

Ett prosjekt, py-spion, bygger en profil for et Python-program ved å sampler samtaleaktiviteten. py-spion kan brukes til å undersøke en kjørende Python-app uten å måtte stoppe og starte den på nytt, og uten å måtte endre kodebasen, slik at den kan brukes til å profilere distribuerte applikasjoner. py-spion genererer også litt statistikk om overhead påløpt av Python runtime (for eksempel søppeloppsamling overhead), som cProfil gjør ikke.

$config[zx-auto] not found$config[zx-overlay] not found