Python-profiler¶
Källkod: Lib/profile.py och Lib/pstats.py
Introduktion till profileringsverktygen¶
cProfile
och profile
ger deterministisk profilering av Python-program. En profile är en uppsättning statistik som beskriver hur ofta och hur länge olika delar av programmet kördes. Denna statistik kan formateras till rapporter via modulen pstats
.
Pythons standardbibliotek tillhandahåller två olika implementeringar av samma profileringsgränssnitt:
cProfile
rekommenderas för de flesta användare; det är ett C-tillägg med rimlig overhead som gör det lämpligt för profilering av långkörande program. Baserat pålsprof
, med bidrag från Brett Rosen och Ted Czotter.profile
, en ren Python-modul vars gränssnitt imiteras avcProfile
, men som lägger till betydande overhead till profilerade program. Om du försöker utöka profileraren på något sätt kan uppgiften vara enklare med den här modulen. Ursprungligen designad och skriven av Jim Roskind.
Anteckning
Profilermodulerna är utformade för att ge en exekveringsprofil för ett visst program, inte för benchmarking (för det finns timeit
för rimligt exakta resultat). Detta gäller särskilt för benchmarking av Python-kod mot C-kod: profilerarna introducerar overhead för Python-kod, men inte för funktioner på C-nivå, och därför skulle C-koden verka snabbare än någon Python-kod.
Användarmanual för Instant¶
Det här avsnittet är avsett för användare som ”inte vill läsa manualen” Det ger en mycket kort översikt och gör det möjligt för en användare att snabbt utföra profilering på en befintlig applikation.
För att profilera en funktion som tar ett enda argument kan du göra så här:
import cProfile
import re
cProfile.run('re.compile("foo|bar")')
(Använd profile
i stället för cProfile
om den senare inte finns tillgänglig i ditt system)
Ovanstående åtgärd skulle köra re.compile()
och skriva ut profilresultat som följande:
214 funktionsanrop (207 primitiva anrop) på 0,002 sekunder
Ordnad efter: kumulativ tid
ncalls tottime percall cumtime percall filnamn:lineno(funktion)
1 0,000 0,000 0,002 0,002 {inbyggd metod builtins.exec}
1 0,000 0,000 0,001 0,001 <string>:1(<module>)
1 0,000 0,000 0,001 0,001 __init__.py:250(kompilera)
1 0,000 0,000 0,001 0,001 __init__.py:289(_kompilering)
1 0,000 0,000 0,000 0,000 _compiler.py:759(kompilera)
1 0,000 0,000 0,000 0,000 _parser.py:937(parse)
1 0,000 0,000 0,000 0,000 _compiler.py:598(_code)
1 0,000 0,000 0,000 0,000 0,000 _parser.py:435(_parse_sub)
Den första raden visar att 214 anrop övervakades. Av dessa anrop var 207 primitive, vilket betyder att anropet inte inducerades via rekursion. Nästa rad: Ordered by: cumulative time
anger att utdata är sorterade efter cumtime
-värdena. Kolumnrubrikerna inkluderar:
- ncalls
för antalet samtal.
- tottid
för den totala tid som tillbringats i den givna funktionen (och exklusive tid för anrop till underfunktioner)
- per telefon
är kvoten av
tottime
dividerat medncalls
- cumtime
är den ackumulerade tid som använts i denna och alla underfunktioner (från anrop till avslut). Denna siffra är korrekt även för rekursiva funktioner.
- per telefon
är kvoten av
cumtime
dividerat med primitiva anrop- filnamn:lineno(funktion)
tillhandahåller respektive data för varje funktion
När det finns två siffror i den första kolumnen (t.ex. 3/1
) betyder det att funktionen recursade. Det andra värdet är antalet primitiva anrop och det första är det totala antalet anrop. Observera att när funktionen inte recurserar är dessa två värden desamma och endast den enda siffran skrivs ut.
I stället för att skriva ut resultatet i slutet av profilkörningen kan du spara resultatet i en fil genom att ange ett filnamn i funktionen run()
:
import cProfile
import re
cProfile.run('re.compile("foo|bar")', 'restats')
Klassen pstats.Stats
läser in profilresultat från en fil och formaterar dem på olika sätt.
Filerna cProfile
och profile
kan också användas som ett skript för att profilera ett annat skript. Till exempel:
python -m cProfile [-o output_file] [-s sort_order] (-m modul | myscript.py)
- -o <output_file>¶
Skriver profilresultaten till en fil i stället för till stdout.
- -s <sort_order>¶
Anger ett av sorteringsvärdena i
sort_stats()
för att sortera utdata efter. Detta gäller endast när-o
inte anges.
- -m <module>¶
Anger att det är en modul som profileras i stället för ett skript.
Tillagd i version 3.7: Alternativet
-m
lades till icProfile
.Tillagd i version 3.8: Alternativet
-m
lades till iprofile
.
Modulen pstats
klass Stats
har en mängd olika metoder för att manipulera och skriva ut data som sparats i en profilresultatfil:
import pstats
from pstats import SortKey
p = pstats.Stats('restats')
p.strip_dirs().sort_stats(-1).print_stats()
Metoden strip_dirs()
tog bort den främmande sökvägen från alla modulnamn. Metoden sort_stats()
sorterade alla poster enligt den standardsträng för modul/rad/namn som skrivs ut. Metoden print_stats()
skrev ut all statistik. Du kan prova följande sorteringsanrop:
p.sort_stats(SortKey.NAME)
p.print_stats()
Det första anropet sorterar faktiskt listan efter funktionsnamn och det andra anropet skriver ut statistiken. Följande är några intressanta anrop att experimentera med:
p.sort_stats(SortKey.CUMULATIVE).print_stats(10)
Detta sorterar profilen efter kumulativ tid i en funktion och skriver sedan bara ut de tio mest betydelsefulla raderna. Om du vill förstå vilka algoritmer som tar tid är det raden ovan som du ska använda.
Om du ville se vilka funktioner som loopade mycket och tog mycket tid, skulle du göra:
p.sort_stats(SortKey.TIME).print_stats(10)
för att sortera efter tidsåtgång inom varje funktion och sedan skriva ut statistiken för de tio bästa funktionerna.
Du kan också prova:
p.sort_stats(SortKey.FILENAME).print_stats('__init__')
Detta sorterar all statistik efter filnamn och skriver sedan ut statistik för endast klassens init-metoder (eftersom de stavas med __init__
i sig). Som ett sista exempel kan du prova:
p.sort_stats(SortKey.TIME, SortKey.CUMULATIVE).print_stats(.5, 'init')
Denna rad sorterar statistik med en primär nyckel för tid och en sekundär nyckel för kumulativ tid, och skriver sedan ut en del av statistiken. För att vara specifik, gallras listan först ner till 50% (re: .5
) av sin ursprungliga storlek, sedan behålls endast rader som innehåller init
, och den under-sub-listan skrivs ut.
Om du undrade vilka funktioner som kallade ovanstående funktioner, kan du nu (p
är fortfarande sorterad enligt det sista kriteriet) göra:
p.print_callers(.5, 'init')
och du får en lista över personer som ringer för var och en av de listade funktionerna.
Om du vill ha fler funktioner måste du läsa manualen eller gissa vad följande funktioner gör:
p.print_callees()
p.add('restats')
Modulen pstats
anropas som ett skript och är en statistikbläddrare för läsning och granskning av profildumpar. Den har ett enkelt linjeorienterat gränssnitt (implementerat med hjälp av cmd
) och interaktiv hjälp.
profile
och cProfile
Modulreferens¶
Både modulerna profile
och cProfile
innehåller följande funktioner:
- profile.run(command, filename=None, sort=-1)¶
Denna funktion tar ett enda argument som kan skickas till
exec()
-funktionen, och ett valfritt filnamn. I samtliga fall exekveras denna rutin:exec(kommando, __main__.__dict__, __main__.__dict__)
och samlar in profileringsstatistik från körningen. Om det inte finns något filnamn skapar funktionen automatiskt en
Stats
-instans och skriver ut en enkel profileringsrapport. Om sorteringsvärdet anges skickas det till dennaStats
-instans för att styra hur resultaten ska sorteras.
- profile.runctx(command, globals, locals, filename=None, sort=-1)¶
Den här funktionen liknar
run()
, med extra argument för att ange mappningarna för globals och locals för command-strängen. Den här rutinen exekverar:exec(kommando, globals, locals)
och samlar in profileringsstatistik som i funktionen
run()
ovan.
- class profile.Profile(timer=None, timeunit=0.0, subcalls=True, builtins=True)¶
Den här klassen används normalt bara om det behövs mer exakt kontroll över profileringen än vad funktionen
cProfile.run()
ger.En egen timer kan tillhandahållas för att mäta hur lång tid det tar för koden att köras via argumentet timer. Detta måste vara en funktion som returnerar ett enda tal som representerar den aktuella tiden. Om talet är ett heltal anger timeunit en multiplikator som anger varaktigheten för varje tidsenhet. Om timern t.ex. returnerar tider som mäts i tusendelar av sekunder, är tidsenheten
.001
.Genom att direkt använda klassen
Profile
kan du formatera profilresultat utan att skriva profildata till en fil:import cProfile, pstats, io från pstats import SortKey pr = cProfile.profil() pr.enable() # ... gör något ... pr.disable() s = io.StringIO() sortby = SortKey.CUMULATIVE ps = pstats.Stats(pr, stream=s).sort_stats(sortby) ps.print_stats() print(s.getvalue())
Klassen
Profile
kan också användas som en kontexthanterare (stöds endast i modulencProfile
. se Typer av kontexthanterare):import cProfile med cProfile.Profile() som pr: # ... gör något ... pr.print_stats()
Ändrad i version 3.8: Stöd för kontexthanterare har lagts till.
- create_stats()¶
Sluta samla in profileringsdata och registrera resultaten internt som den aktuella profilen.
- print_stats(sort=-1)¶
Skapa ett
Stats
-objekt baserat på den aktuella profilen och skriv ut resultaten till stdout.Parametern sort anger sorteringsordningen för den statistik som visas. Den accepterar en enda nyckel eller en tupel av nycklar för att möjliggöra sortering på flera nivåer, som i
Stats.sort_stats
.Tillagd i version 3.13:
print_stats()
accepterar nu en tupel av nycklar.
- dump_stats(filename)¶
Skriv resultatet av den aktuella profilen till filnamn.
- runcall(func, /, *args, **kwargs)¶
Profil
func(*args, **kwargs)
Observera att profileringen endast fungerar om det anropade kommandot/funktionen faktiskt returneras. Om tolken avslutas (t.ex. via ett sys.exit()
-anrop under exekveringen av det anropade kommandot/funktionen) kommer inga profileringsresultat att skrivas ut.
Klassen Stats
¶
Analys av profileringsdata görs med hjälp av klassen Stats
.
- class pstats.Stats(*filenames or profile, stream=sys.stdout)¶
Denna klasskonstruktor skapar en instans av ett ”statistikobjekt” från ett filnamn (eller en lista med filnamn) eller från en
Profile
-instans. Utdata kommer att skrivas ut till den ström som anges av stream.Den fil som väljs av ovanstående konstruktör måste ha skapats av motsvarande version av
profile
ellercProfile
. För att vara specifik, det finns ingen garanterad filkompatibilitet med framtida versioner av denna profilerare, och det finns ingen kompatibilitet med filer som producerats av andra profilerare, eller samma profilerare som körs på ett annat operativsystem. Om flera filer tillhandahålls kommer all statistik för identiska funktioner att sammanställas, så att en övergripande bild av flera processer kan beaktas i en enda rapport. Om ytterligare filer behöver kombineras med data i ett befintligtStats
-objekt, kan metodenadd()
användas.I stället för att läsa profildata från en fil kan ett
cProfile.Profile
- ellerprofile.Profile
-objekt användas som profildatakälla.Stats
-objekt har följande metoder:- strip_dirs()¶
Den här metoden för klassen
Stats
tar bort all inledande sökvägsinformation från filnamn. Det är mycket användbart för att minska storleken på utskriften så att den ryms inom (nära) 80 kolumner. Den här metoden ändrar objektet och den borttagna informationen går förlorad. Efter att ha utfört en strippning anses objektet ha sina poster i en ”slumpmässig” ordning, som den var precis efter initialisering och laddning av objektet. Omstrip_dirs()
gör att två funktionsnamn inte går att skilja åt (de står på samma rad i samma filnamn och har samma funktionsnamn), ackumuleras statistiken för dessa två poster till en enda post.
- add(*filenames)¶
Denna metod i klassen
Stats
ackumulerar ytterligare profileringsinformation i det aktuella profileringsobjektet. Dess argument bör referera till filnamn som skapats av motsvarande version avprofile.run()
ellercProfile.run()
. Statistik för identiskt namngivna (re: fil, rad, namn) funktioner ackumuleras automatiskt till statistik för en enda funktion.
- dump_stats(filename)¶
Spara data som laddats i objektet
Stats
till en fil med namnet filnamn. Filen skapas om den inte finns, och skrivs över om den redan finns. Detta är likvärdigt med metoden med samma namn i klassernaprofile.Profile
ochcProfile.Profile
.
- sort_stats(*keys)¶
Denna metod modifierar
Stats
-objektet genom att sortera det enligt de angivna kriterierna. Argumentet kan vara antingen en sträng eller ett SortKey-enum som identifierar grunden för en sortering (exempel:'time'
,'name'
,SortKey.TIME
ellerSortKey.NAME
). Argumentet SortKey enums har en fördel jämfört med strängargumentet genom att det är mer robust och mindre felbenäget.När mer än en nyckel anges används ytterligare nycklar som sekundära kriterier när det råder likhet mellan alla nycklar som valts före dem. Exempelvis sorterar
sort_stats(SortKey.NAME, SortKey.FILE)
alla poster efter deras funktionsnamn och löser alla oavgjorda frågor (identiska funktionsnamn) genom att sortera efter filnamn.För strängargumentet kan förkortningar användas för alla nyckelnamn, så länge förkortningen är entydig.
Följande är giltiga strängar och SortKey:
Giltig sträng Arg
Giltig enum Arg
Betydelse
'calls'
SortKey.CALLS
antal samtal
'cumulative'
SortKey.KUMULATIV
kumulativ tid
'cumtime'
N/A
kumulativ tid
'file'
N/A
filnamn
'filename'
SortKey.FILENAME
filnamn
'module'
N/A
filnamn
'ncalls'
N/A
antal samtal
'pcalls'
Sorteringsnyckel.PCALLS
antal primitiva samtal
'line'
Sorteringsnyckel.LINJE
radnummer
'name'
Sorteringsnyckel.namn
funktionsnamn
'nfl'
Sorteringsnyckel.NFL
namn/fil/rad
'stdname'
SortKey.STDNAME
standardnamn
'time'
Sorteringsnyckel.TIME
intern tid
'tottime'
N/A
intern tid
Observera att alla sorteringar av statistik är i fallande ordning (de mest tidskrävande först), medan sökningar efter namn, filer och radnummer är i stigande ordning (alfabetisk). Den subtila skillnaden mellan
SortKey.NFL
ochSortKey.STDNAME
är att standardnamnet är en sortering av namnet som det skrivs ut, vilket innebär att de inbäddade radnumren jämförs på ett udda sätt. Till exempel skulle raderna 3, 20 och 40 (om filnamnen var desamma) visas i strängordningen 20, 3 och 40. Däremot görSortKey.NFL
en numerisk jämförelse av radnumren. I själva verket ärSort_stats(SortKey.NFL)
samma sak somSort_stats(SortKey.NAME, SortKey.FILENAME, SortKey.LINE)
.Av bakåtkompatibilitetsskäl är de numeriska argumenten
-1
,0
,1
och2
tillåtna. De tolkas som'stdname'
,'calls'
,'time'
respektive'cumulative'
. Om detta gamla format (numeriskt) används, kommer endast en sorteringsnyckel (den numeriska nyckeln) att användas, och ytterligare argument kommer att ignoreras.Tillagd i version 3.7: Enumret SortKey har lagts till.
- reverse_order()¶
Denna metod för klassen
Stats
reverserar ordningen på grundlistan i objektet. Observera att som standard väljs stigande eller fallande ordning korrekt baserat på den valda sorteringsnyckeln.
- print_stats(*restrictions)¶
Denna metod för klassen
Stats
skriver ut en rapport enligt beskrivningen i definitionenprofile.run()
.Ordningen på utskriften baseras på den senaste
sort_stats()
-operationen som gjordes på objektet (med förbehåll för förbehåll iadd()
ochstrip_dirs()
).De argument som anges (om några) kan användas för att begränsa listan till de viktiga posterna. Inledningsvis antas listan vara den fullständiga uppsättningen profilerade funktioner. Varje begränsning är antingen ett heltal (för att välja ett antal rader), en decimal mellan 0,0 och 1,0 (för att välja en procentandel av raderna) eller en sträng som tolkas som ett reguljärt uttryck (för att matcha det standardnamn som skrivs ut). Om flera begränsningar anges tillämpas de i tur och ordning. Exempel:
print_stats(.1, 'foo:')
skulle först begränsa utskriften till den första 10% of-listan och sedan bara skriva ut funktioner som ingick i filnamnet
.*foo:
. I motsats till detta skulle kommandot:print_stats('foo:', .1)
skulle begränsa listan till alla funktioner som har filnamnen
.*foo:
, och sedan bara skriva ut de första 10% of dem.
- print_callers(*restrictions)¶
Denna metod för klassen
Stats
skriver ut en lista över alla funktioner som anropade varje funktion i den profilerade databasen. Ordningen är identisk med den som tillhandahålls avprint_stats()
, och definitionen av det begränsande argumentet är också identisk. Varje uppringare rapporteras på en egen rad. Formatet skiljer sig något beroende på vilken profilerare som producerade statistiken:Med
profile
visas ett tal inom parentes efter varje uppringare för att visa hur många gånger just detta uppringande gjordes. För enkelhetens skull upprepar en andra siffra utan parentes den sammanlagda tid som tillbringats i funktionen till höger.Med
cProfile
föregås varje anrop av tre siffror: antalet gånger som det specifika anropet gjordes och den totala och kumulativa tid som spenderades i den aktuella funktionen när den anropades av den specifika anroparen.
- print_callees(*restrictions)¶
Denna metod för klassen
Stats
skriver ut en lista över alla funktioner som anropades av den angivna funktionen. Bortsett från denna omkastning av anropens riktning (re: called vs was called by) är argumenten och ordningen identiska med metodenprint_callers()
.
- get_stats_profile()¶
Denna metod returnerar en instans av StatsProfile, som innehåller en mappning av funktionsnamn till instanser av FunctionProfile. Varje FunctionProfile-instans innehåller information som är relaterad till funktionens profil, t.ex. hur lång tid det tog för funktionen att köras, hur många gånger den anropades osv.
Tillagd i version 3.9: Lade till följande dataklasser: StatsProfile, FunctionProfile. Följande funktion lades till: get_stats_profile.
Vad är deterministisk profilering?¶
Deterministic profiling är tänkt att återspegla det faktum att alla händelser av typen funktionsanrop, funktionsretur och undantag övervakas och att exakta tidsangivelser görs för intervallen mellan dessa händelser (under vilken tid användarens kod exekveras). Vid statistical profiling (som inte görs av den här modulen) görs däremot slumpmässiga stickprov på den effektiva instruktionspekaren och man drar slutsatser om var tiden spenderas. Den senare tekniken innebär traditionellt mindre overhead (eftersom koden inte behöver instrumenteras), men ger bara relativa indikationer på var tiden spenderas.
I Python, eftersom det finns en tolk som är aktiv under exekveringen, krävs det inte att det finns instrumenterad kod för att göra en deterministisk profilering. Python tillhandahåller automatiskt en hook (valfri callback) för varje händelse. Dessutom tenderar Pythons tolkade natur att lägga till så mycket overhead till exekveringen att deterministisk profilering tenderar att bara lägga till liten bearbetningsoverhead i typiska applikationer. Resultatet är att deterministisk profilering inte är särskilt dyr, men ändå ger omfattande körtidsstatistik om körningen av ett Python-program.
Statistik över antal anrop kan användas för att identifiera buggar i koden (överraskande antal anrop) och för att identifiera möjliga punkter för inline-expansion (högt antal anrop). Intern tidsstatistik kan användas för att identifiera ”heta loopar” som bör optimeras noggrant. Kumulativ tidsstatistik bör användas för att identifiera högnivåfel i valet av algoritmer. Observera att den ovanliga hanteringen av kumulativa tider i den här profileraren gör att statistik för rekursiva implementeringar av algoritmer kan jämföras direkt med iterativa implementeringar.
Begränsningar¶
En begränsning har att göra med noggrannheten i tidsinformationen. Det finns ett grundläggande problem med deterministiska profilerare som rör noggrannhet. Den mest uppenbara begränsningen är att den underliggande ”klockan” bara tickar med en hastighet (typiskt) på cirka 0,001 sekunder. Därför kommer inga mätningar att vara mer exakta än den underliggande klockan. Om tillräckligt många mätningar görs tenderar ”felet” att jämna ut sig. Om man tar bort detta första fel uppstår tyvärr en andra felkälla.
Det andra problemet är att det ”tar ett tag” från det att en händelse skickas till dess att profilerarens anrop för att få tiden faktiskt får klockans tillstånd. På samma sätt finns det en viss fördröjning när man lämnar profileringshändelsehanteraren från det att klockans värde erhölls (och sedan gömdes undan) tills användarens kod återigen körs. Därför kommer funktioner som anropas många gånger, eller som anropar många funktioner, vanligtvis att ackumulera detta fel. Felet som ackumuleras på detta sätt är vanligtvis mindre än klockans noggrannhet (mindre än ett klockslag), men det kan ackumuleras och bli mycket betydande.
Problemet är större med profile
än med den mindre avancerade cProfile
. Av denna anledning tillhandahåller profile
ett sätt att kalibrera sig själv för en given plattform så att detta fel kan tas bort på ett probabilistiskt sätt (i genomsnitt). När profileraren har kalibrerats kommer den att vara mer exakt (i minsta kvadrat-led), men den kommer ibland att producera negativa siffror (när antalet anrop är exceptionellt lågt och sannolikhetens gudar arbetar emot dig :-). ) Låt dig inte skrämmas av negativa siffror i profilen. De ska endast visas om du har kalibrerat din profilerare och resultaten faktiskt är bättre än utan kalibrering.
Kalibrering¶
Profileraren i modulen profile
subtraherar en konstant från varje händelsehanteringstid för att kompensera för omkostnaderna för att anropa tidsfunktionen och lagra resultaten. Som standard är konstanten 0. Följande procedur kan användas för att få en bättre konstant för en viss plattform (se Begränsningar).
import profile
pr = profile.Profile()
for i in range(5):
print(pr.calibrate(10000))
Metoden kör det antal Python-anrop som anges i argumentet, direkt och igen under profileraren, och mäter tiden för båda. Den beräknar sedan den dolda overhead per profileringshändelse och returnerar den som en float. Till exempel, på en 1,8 GHz Intel Core i5 som kör macOS och använder Pythons time.process_time() som timer, är det magiska talet cirka 4,04e-6.
Syftet med den här övningen är att få ett någorlunda konsekvent resultat. Om din dator är mycket snabb, eller om din timerfunktion har dålig upplösning, kan du behöva passera 100000, eller till och med 1000000, för att få konsekventa resultat.
När du har ett konsekvent svar kan du använda det på tre sätt:
importprofil
# 1. Tillämpa beräknad bias på alla profilinstanser som skapas hädanefter.
profile.Profile.bias = din_beräknade_bias
# 2. Tillämpa beräknad förspänning på en specifik profilinstans.
pr = profile.Profile()
pr.bias = din_beräknade_bias
# 3. Ange beräknad förspänning i instansens konstruktör.
pr = profile.Profile(bias=din_beräknade_bias)
Om du har ett val är det bättre att du väljer en mindre konstant, och då kommer dina resultat ”mindre ofta” att visa sig vara negativa i profilstatistiken.
Använda en anpassad timer¶
Om du vill ändra hur aktuell tid bestäms (t.ex. för att tvinga fram användning av väggklockans tid eller förfluten processtid), skickar du den tidsfunktion du vill ha till Profile
-klassens konstruktör:
pr = profil.Profil(din_tid_func)
Den resulterande profileraren kommer sedan att anropa your_time_func
. Beroende på om du använder profile.Profile
eller cProfile.Profile
, kommer your_time_func
’s returvärde att tolkas på olika sätt:
profile.Profile
your_time_func
bör returnera ett enda tal, eller en lista med tal vars summa är den aktuella tiden (som vados.times()
returnerar). Om funktionen returnerar ett enda tidsnummer, eller om listan med returnerade nummer har längden 2, får du en särskilt snabb version av sändningsrutinen.Tänk på att du bör kalibrera profileringsklassen för den timerfunktion du väljer (se Kalibrering). För de flesta maskiner kommer en timer som returnerar ett ensamt heltalsvärde att ge de bästa resultaten när det gäller låg overhead under profileringen. (
os.times()
är ganska dålig, eftersom den returnerar en tupel av flyttalsvärden). Om du vill byta ut en bättre timer på det renaste sättet, härled en klass och hårdkoppla en ersättande dispatch-metod som bäst hanterar ditt timeranrop, tillsammans med lämplig kalibreringskonstant.cProfile.Profile
your_time_func
bör returnera ett enda tal. Om den returnerar heltal kan du också anropa klasskonstruktören med ett andra argument som anger den verkliga varaktigheten för en tidsenhet. Om till exempelyour_integer_time_func
returnerar tider som mäts i tusentals sekunder, skulle du konstrueraProfile
-instansen på följande sätt:pr = cProfile.Profile(din_integer_tid_func, 0,001)
Eftersom klassen
cProfile.Profile
inte kan kalibreras, bör anpassade timerfunktioner användas med försiktighet och vara så snabba som möjligt. För bästa resultat med en egen timer kan det vara nödvändigt att hårdkoda den i C-källan för den interna_lsprof
-modulen.
Python 3.3 lägger till flera nya funktioner i time
som kan användas för att göra exakta mätningar av process- eller väggklocktid. Se till exempel time.perf_counter()
.