Kako koristiti cProfile za profiliranje Python koda

Python možda nije najbrži jezik, ali je često dovoljno brz. A Python je idealan kada je vrijeme programera važnije od CPU vremena.

To je reklo, ako je zadana aplikacija Python zaostala, ne morate je samo usisati. Alati uključeni u instalacijsku instalaciju Python interpretera mogu vam pružiti detaljne povratne informacije o tome koji su dijelovi vašeg programa spori i pružiti neke savjete o tome kako ih ubrzati.

Kako koristiti cProfile

cProfileModul okuplja statistike o vremenu izvršenja Python programa. Može izvještavati o bilo čemu, od cijele aplikacije do jedne izjave ili izraza.

Evo primjera igračke kako koristiti cProfile:

def add (x, y): x + = str (y) return x def add_2 (x, y): if y% 20000 == 0: z = [] za q u rasponu (0,400000): z.append ( q) def main (): a = [] za n u rasponu (0,200000): dodaj (a, n) dodaj_2 (a, n) ako je __name__ == '__main__': uvoz cProfile cProfile.run ('main ( ) ') 

Ovaj primjer pokreće funkciju aplikacije main()i analizira izvedbu main()i sve main()pozive. Također je moguće analizirati samo  dio programa, ali najčešća upotreba za početak je profiliranje cijelog programa.

Pokrenite gornji primjer i dobit ćete nešto poput sljedećeg rezultata:

Ovdje je prikazan popis svih poziva funkcija koje je program izvršio, zajedno sa statistikama o svakom:

  • Na vrhu (prvi redak plave boje) vidimo ukupan broj poziva upućenih u profiliranom programu i ukupno vrijeme izvršenja. Možete vidjeti i brojku za "primitivne pozive", što znači nerekurzivne pozive ili pozive upućene izravno funkciji koja se zauzvrat ne poziva niže u nizu poziva.
  • ncalls : broj upućenih poziva. Ako vidite dva broja odvojena kosom crtom, drugi broj je broj primitivnih poziva za tu funkciju.
  • tottime : Ukupno vrijeme provedeno u funkciji, ne uključujući pozive drugim funkcijama.
  • percall : Prosječno vrijeme po pozivu za tottime , dobiveno uzimajući tottime i dijeleći ga s ncalls .
  • cumtime : Ukupno vrijeme provedeno u funkciji, uključujući pozive drugim funkcijama.
  • percall (# 2): Prosječno vrijeme po pozivu za cumtime ( cumtime podijeljeno s ncalls ).
  • naziv datoteke: lineno : Naziv datoteke, broj linije i naziv funkcije za dotični poziv.

Kako izmijeniti izvješća cProfile

Prema zadanim postavkama cProfilesvoj izlaz sortira po "standardnom imenu", što znači da sortira po tekstu u krajnjem desnom stupcu (naziv datoteke, broj retka itd.).

Zadani format koristan je ako želite općenito izvješće odozgo prema dolje za svaki pojedini poziv funkcije za referencu. Ali ako pokušavate doći do dna uskog grla, vjerojatno ćete htjeti prvo nabrojane dijelove programa koji oduzimaju najviše vremena.

Te rezultate možemo proizvesti pozivanjem  cProfile na malo drugačiji način. Imajte na umu kako se donji dio gornjeg programa može preraditi kako bi se statistike razvrstale po drugom stupcu (u ovom slučaju ncalls):

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

Rezultati će izgledati otprilike ovako:

Evo kako sve ovo funkcionira:

  • Umjesto izvršenja naredbe putem cProfile.run(), što nije vrlo fleksibilna, stvaramo profiliranje objekt , profiler.
  • Kada želimo profilirati neku akciju, prvo pozivamo .enable()instancu objekta profilirača , zatim pokrećemo akciju, a zatim pozivamo .disable(). (Ovo je jedan od načina za profiliranje samo dijela programa.)
  • pstatsModul se koristi za manipulaciju rezultate prikupljene od strane Profiler objekta i ispis tih rezultata.

Kombinacija objekta pstatsza profiliranje omogućuje nam manipulaciju snimljenim podacima profila - na primjer, za drugačije sortiranje generirane statistike. U ovom primjeru, korištenje .sort_stats('ncalls')sortira statistiku po ncallsstupcu. Dostupne su i druge opcije sortiranja.

Kako koristiti rezultate cProfile za optimizaciju

Opcije sortiranja dostupne za cProfile izlaz omogućuju nam da riješimo potencijalna uska grla u izvedbi programa.

ncalls

Prva i najznačajnija informacija koju možete otkriti cProfileje koje se funkcije najčešće pozivaju putem ncallsstupca.

U Pythonu puki čin upućivanja poziva funkcije donosi relativno veliku količinu troškova. Ako se neka funkcija više puta poziva u uskoj petlji, čak i ako nije dugotrajna, to će zajamčeno utjecati na performanse.

U gornjem primjeru funkcija add(i funkcija add_2) se pozivaju više puta u petlji. Premještanje petlje u samu addfunkciju ili potpuno umetanje addfunkcije riješilo bi ovaj problem.

tottime

Još jedan koristan statistički detalj koji funkcionira kako program provodi većinu svog vremena izvršavajući se putem tottimestupca.

U gornjem primjeru add_2funkcija koristi petlju za simulaciju skupog izračuna, što gura tottimerezultat na vrh. Svaka funkcija s visokim tottimerezultatom zaslužuje pomni pogled, posebno ako je pozvana više puta ili u uskoj petlji.

Imajte na umu da uvijek trebate uzeti u obzir kontekst  u kojem se funkcija koristi. Ako funkcija ima visoku vrijednost, tottimeali se poziva samo jednom - na primjer, samo kad se program pokrene - manja je vjerojatnost da će biti usko grlo. Međutim, ako pokušavate smanjiti vrijeme pokretanja, morat ćete znati je li funkcija pozvana pri pokretanju sve ostalo na čekanju.

Kako izvesti podatke o cProfileu

Ako želite cProfilegeneriranu statistiku koristiti na naprednije načine, možete je izvesti u podatkovnu datoteku:

statistika = pstats.Stats (profiler) stats.dump_stats ('/ put / do / stats_file.dat') 

Ovu datoteku možete ponovno pročitati pomoću pstatsmodula, zatim sortirati ili prikazati s pstats. Podaci se mogu ponovno koristiti i drugim programima. Dva primjera:

  • pyprof2calltreedaje detaljne vizualizacije grafikona poziva programa i statistike upotrebe iz podataka profila. Ovaj članak daje detaljan stvarni primjer njegove uporabe.
  • snakeviztakođer generira vizualizacije iz cProfilepodataka, ali koristi drugačiji prikaz podataka - "sunčanicu", a ne grafiku "plamena" pyprof2calltree.

Osim cProfila za Python profiliranje

cProfileje jedina mogućnost profiliranja Python aplikacije. cProfileje zasigurno jedan od najprikladnijih načina, s obzirom da je u paketu s Pythonom. Ali drugi zaslužuju pažnju.

Jedan projekt, py-spygradi profil za Python aplikaciju uzorkovanjem aktivnosti poziva. py-spyse može koristiti za ispitivanje pokrenute aplikacije Python bez zaustavljanja i ponovnog pokretanja i bez potrebe za izmjenom baze podataka, tako da se može koristiti za profiliranje postavljenih aplikacija. py-spytakođer generira neke statistike o režijskim troškovima nastalim tijekom izvođenja Pythona (na primjer, režijski troškovi prikupljanja smeća), što cProfilenije.