Hoe kun je een Python-script profileren?

Project Euleren andere codeerwedstrijden hebben vaak een maximale tijdsduur of mensen scheppen op over hoe snel hun specifieke oplossing loopt. Met Python zijn de benaderingen soms wat kludgey – d.w.z. het toevoegen van timingcode aan __main__.

Wat is een goede manier om te profileren hoe lang het duurt voordat een Python-programma wordt uitgevoerd?


Antwoord 1, autoriteit 100%

Python bevat een profiler genaamd cProfile. Het geeft niet alleen de totale looptijd, maar ook de tijden van elke functie afzonderlijk, en vertelt u hoe vaak elke functie is aangeroepen, zodat u gemakkelijk kunt bepalen waar u optimalisaties moet maken.

Je kunt het vanuit je code of vanuit de tolk als volgt aanroepen:

import cProfile
cProfile.run('foo()')

Nog handiger, je kunt het cProfile aanroepen bij het uitvoeren van een script:

python -m cProfile myscript.py

Om het nog makkelijker te maken, heb ik een klein batchbestand gemaakt met de naam ‘profile.bat’:

python -m cProfile %1

Dus ik hoef alleen maar te rennen:

profile euler048.py

En ik begrijp dit:

1007 function calls in 0.061 CPU seconds
Ordered by: standard name
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.000    0.000    0.061    0.061 <string>:1(<module>)
 1000    0.051    0.000    0.051    0.000 euler048.py:2(<lambda>)
    1    0.005    0.005    0.061    0.061 euler048.py:2(<module>)
    1    0.000    0.000    0.061    0.061 {execfile}
    1    0.002    0.002    0.053    0.053 {map}
    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler objects}
    1    0.000    0.000    0.000    0.000 {range}
    1    0.003    0.003    0.003    0.003 {sum}

EDIT: bijgewerkte link naar een goede videobron van Pycon 2013 getiteld
Python profilering
ook via YouTube .


2, Autoriteit 31%

Een tijdje geleden heb ik pycallgraphgemaakt die een visualisatie uit je Python-code genereert . Edit: Ik heb het voorbeeld bijgewerkt om te werken met 3.3, de nieuwste versie vanaf dit schrijven.

Na een pip install pycallgraphen installeren Graphviz U kunt het uit de Opdrachtregel:

pycallgraph graphviz -- ./mypythonscript.py

of, u kunt bepaalde delen van uw code profileren:

from pycallgraph import PyCallGraph
from pycallgraph.output import GraphvizOutput
with PyCallGraph(output=GraphvizOutput()):
    code_to_profile()

Een van deze genereert een pycallgraph.pngbestand vergelijkbaar met de onderstaande afbeelding:


Antwoord 3, autoriteit 14%

Het is de moeite waard om erop te wijzen dat het gebruik van de profiler alleen werkt (standaard) op de hoofdthread, en je krijgt geen informatie van andere threads als je ze gebruikt. Dit kan een beetje een gotcha zijn, aangezien het volledig niet wordt vermeld in de profiler-documentatie.

Als je ook threads wilt profileren, kijk dan eens naar de titel threading.setprofile()functiein de documenten.

Je zou ook je eigen threading.Threadsubklasse kunnen maken om dit te doen:

class ProfiledThread(threading.Thread):
    # Overrides threading.Thread.run()
    def run(self):
        profiler = cProfile.Profile()
        try:
            return profiler.runcall(threading.Thread.run, self)
        finally:
            profiler.dump_stats('myprofile-%d.profile' % (self.ident,))

en gebruik die klasse ProfiledThreadin plaats van de standaardklasse. Het geeft je misschien meer flexibiliteit, maar ik weet niet zeker of het de moeite waard is, vooral als je code van derden gebruikt die je klas niet zou gebruiken.


Antwoord 4, autoriteit 11%

De python-wiki is een geweldige pagina voor het profileren van bronnen:
http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code

net als de python-documenten:
http://docs.python.org/library/profile.html

zoals getoond door Chris Lawlor cProfile is een geweldig hulpmiddel en kan gemakkelijk worden gebruikt om naar het scherm af te drukken:

python -m cProfile -s time mine.py <args>

of naar bestand:

python -m cProfile -o output.file mine.py <args>

PS> Als u Ubuntu gebruikt, zorg er dan voor dat u python-profile

. installeert

apt-get install python-profiler 

Als je uitvoer naar een bestand, kun je mooie visualisaties krijgen met de volgende tools

PyCallGraph: een tool om oproepgrafieken te maken
installeren:

pip install pycallgraph

rennen:

pycallgraph mine.py args

bekijken:

gimp pycallgraph.png

Je kunt alles gebruiken wat je wilt om het png-bestand te bekijken, ik heb gimp gebruikt
Helaas krijg ik vaak

punt: grafiek is te groot voor caïro-renderer bitmaps. Schalen met 0,257079 om te passen

waardoor mijn afbeeldingen onbruikbaar klein worden. Dus ik maak over het algemeen svg-bestanden:

pycallgraph -f svg -o pycallgraph.svg mine.py <args>

PS> zorg ervoor dat u graphviz installeert (dat het puntprogramma levert):

pip install graphviz

Alternatieve grafieken met gprof2dot via @maxy / @quodlibetor :

pip install gprof2dot
python -m cProfile -o profile.pstats mine.py
gprof2dot -f pstats profile.pstats | dot -Tsvg -o mine.svg

Antwoord 5, autoriteit 10%

@Maxy’s opmerking op dit antwoordheeft me voldoende geholpen dat ik denk dat het een eigen antwoord verdient: ik had al cProfile -gegenereerde .pstats-bestanden en ik wilde dingen niet opnieuw uitvoeren met pycallgraph, dus gebruikte ik gprof2dot, en kreeg mooie svg’s:

$ sudo apt-get install graphviz
$ git clone https://github.com/jrfonseca/gprof2dot
$ ln -s "$PWD"/gprof2dot/gprof2dot.py ~/bin
$ cd $PROJECT_DIR
$ gprof2dot.py -f pstats profile.pstats | dot -Tsvg -o callgraph.svg

en BLAM!

Het gebruikt punt (hetzelfde dat pycallgraph gebruikt), dus de uitvoer ziet er hetzelfde uit. Ik krijg echter de indruk dat gprof2dot minder informatie verliest:


Antwoord 6, autoriteit 7%

De eenvoudigsteen snelstemanier om te vinden waar de hele tijd naartoe gaat.

1. pip install snakeviz
2. python -m cProfile -o temp.dat <PROGRAM>.py
3. snakeviz temp.dat

Trekt een cirkeldiagram in een browser. Grootste stuk is de probleemfunctie. Heel eenvoudig.


Antwoord 7, autoriteit 6%

Ik kwam een handige tool tegen met de naam SnakeVizbij het onderzoeken van dit onderwerp. SnakeViz is een webgebaseerde visualisatietool voor profilering. Het is heel gemakkelijk te installeren en te gebruiken. De gebruikelijke manier waarop ik het gebruik is om een stat-bestand te genereren met %prunen vervolgens analyse uit te voeren in SnakeViz.

De belangrijkste viz-techniek die wordt gebruikt is Sunburst-diagramzoals hieronder weergegeven, waarin de hiërarchie van functieaanroepen is gerangschikt als lagen van bogen en tijdinfo gecodeerd in hun hoekbreedtes.

Het beste is dat u kunt communiceren met de grafiek. Om bijvoorbeeld in te zoomen kan men op een boog klikken, en de boog en zijn afstammelingen worden vergroot als een nieuwe zonnestraal om meer details weer te geven.


Antwoord 8, autoriteit 5%

cProfileis geweldig voor profilering, terwijl kcachegrindis geweldig voor het visualiseren van de resultaten. De pyprof2calltreedaartussen zorgt voor de bestandsconversie.

python -m cProfile -o script.profile script.py
pyprof2calltree -i script.profile -o script.calltree
kcachegrind script.calltree

Vereiste systeempakketten:

  • kcachegrind(Linux), qcachegrind(MacOs)

Instellen op Ubuntu:

apt-get install kcachegrind 
pip install pyprof2calltree

Het resultaat:


Antwoord 9, autoriteit 3%

Ik heb onlangs tonijngemaakt voor het visualiseren van Python-runtime en importprofielen; dit kan hier nuttig zijn.

Installeren met

pip install tuna

Maak een runtime-profiel

python3 -m cProfile -o program.prof yourfile.py

of een importprofiel (Python 3.7+ vereist)

python3 -X importprofile yourfile.py 2> import.log

Voer dan gewoon tonijn uit op het bestand

tuna program.prof

Antwoord 10, autoriteit 3%

Ook het vermelden waard is de GUI cProfile dumpviewer RunSnakeRun. Hiermee kunt u sorteren en selecteren, en daarmee inzoomen op de relevante onderdelen van het programma. De afmetingen van de rechthoeken in de afbeelding zijn evenredig met de tijd die nodig is. Als u met de muis over een rechthoek gaat, wordt die oproep in de tabel en overal op de kaart gemarkeerd. Wanneer u dubbelklikt op een rechthoek, zoomt deze in op dat gedeelte. Het zal je laten zien wie dat deel noemt en wat dat deel noemt.

De beschrijvende informatie is erg nuttig. Het toont u de code voor dat bit, wat handig kan zijn als u te maken hebt met ingebouwde bibliotheekaanroepen. Het vertelt je in welk bestand en op welke regel de code moet worden gevonden.

Ik wil er ook op wijzen dat de OP ‘profilering’ zei, maar het lijkt erop dat hij ‘timing’ bedoelde. Houd er rekening mee dat programma’s langzamer werken als ze zijn geprofileerd.


Antwoord 11, autoriteit 2%

pprofile

line_profiler(reeds hier gepresenteerd) inspireerde ook pprofile, wat wordt beschreven als:

Lijngranulariteit, draadbewuste deterministische en statistische pure-python
profiler

Het biedt regelgranulariteit als line_profiler, is pure Python, kan worden gebruikt als een op zichzelf staande opdracht of een module, en kan zelfs bestanden in callgrind-indeling genereren die eenvoudig kunnen worden geanalyseerd met [k|q]cachegrind.

vprof

Er is ook vprof, een Python-pakket dat wordt beschreven als:

[…] biedt rijke en interactieve visualisaties voor verschillende Python-programmakenmerken, zoals looptijd en geheugengebruik.


Antwoord 12, autoriteit 2%

Een mooie profileringsmodule is de line_profiler (aangeroepen met het script kernprof.py). Het kan hierworden gedownload.

Ik heb begrepen dat cProfile alleen informatie geeft over de totale tijd die aan elke functie is besteed. Afzonderlijke coderegels zijn dus niet getimed. Dit is een probleem bij wetenschappelijke informatica, omdat één enkele regel vaak veel tijd in beslag kan nemen. Ook, zoals ik me herinner, ving cProfile niet de tijd die ik doorbracht in zeg numpy.dot.


Antwoord 13

Er zijn veel goede antwoorden, maar ze gebruiken de opdrachtregel of een extern programma om de resultaten te profileren en/of te sorteren.

Ik heb echt een manier gemist die ik in mijn IDE (eclipse-PyDev) kon gebruiken zonder de opdrachtregel aan te raken of iets te installeren. Dus hier is het.

Profileren zonder opdrachtregel

def count():
    from math import sqrt
    for x in range(10**5):
        sqrt(x)
if __name__ == '__main__':
    import cProfile, pstats
    cProfile.run("count()", "{}.profile".format(__file__))
    s = pstats.Stats("{}.profile".format(__file__))
    s.strip_dirs()
    s.sort_stats("time").print_stats(10)

Zie docsof andere antwoorden voor meer informatie.


Antwoord 14

De terminal-only (en eenvoudigste) oplossing, voor het geval al die mooie UI’s niet kunnen worden geïnstalleerd of uitgevoerd:
negeer cProfilevolledig en vervang het door pyinstrument, dat de boom met oproepen direct na uitvoering zal verzamelen en weergeven.

Installeren:

$ pip install pyinstrument

Profiel en weergaveresultaat:

$ python -m pyinstrument ./prog.py

Werkt met python2 en 3.

[BEWERKEN]
De documentatie van de API, voor het profileren van slechts een deel van de code, is te vinden hier.


Antwoord 15

Na het antwoord van Joe Shaw dat multi-threaded code niet werkte zoals verwacht, bedacht ik dat de runcall-methode in cProfile alleen maar self.enable()en self.disable()roept rond de geprofileerde functie-aanroep, dus je kunt dat gewoon zelf doen en tussen de code hebben die je wilt met minimale interferentie met bestaande code.


Antwoord 16

In Virtaal’s bronstaat een zeer nuttige klasse en decorateur die profilering (zelfs voor specifieke methoden/functies) zeer eenvoudig kan maken. De uitvoer kan dan heel comfortabel worden bekeken in KCacheGrind.


Antwoord 17

Als u een cumulatieve profiler wilt maken,
wat betekent dat de functie meerdere keren achter elkaar moet worden uitgevoerd en de som van de resultaten moet worden bekeken.

je kunt deze cumulative_profilerdecorateur gebruiken:

het is specifiek voor python >= 3.6, maar je kunt nonlocalverwijderen omdat het werkt op oudere versies.

import cProfile, pstats
class _ProfileFunc:
    def __init__(self, func, sort_stats_by):
        self.func =  func
        self.profile_runs = []
        self.sort_stats_by = sort_stats_by
    def __call__(self, *args, **kwargs):
        pr = cProfile.Profile()
        pr.enable()  # this is the profiling section
        retval = self.func(*args, **kwargs)
        pr.disable()
        self.profile_runs.append(pr)
        ps = pstats.Stats(*self.profile_runs).sort_stats(self.sort_stats_by)
        return retval, ps
def cumulative_profiler(amount_of_times, sort_stats_by='time'):
    def real_decorator(function):
        def wrapper(*args, **kwargs):
            nonlocal function, amount_of_times, sort_stats_by  # for python 2.x remove this row
            profiled_func = _ProfileFunc(function, sort_stats_by)
            for i in range(amount_of_times):
                retval, ps = profiled_func(*args, **kwargs)
            ps.print_stats()
            return retval  # returns the results of the function
        return wrapper
    if callable(amount_of_times):  # incase you don't want to specify the amount of times
        func = amount_of_times  # amount_of_times is the function in here
        amount_of_times = 5  # the default amount
        return real_decorator(func)
    return real_decorator

voorbeeld

Profilering van de functie baz

import time
@cumulative_profiler
def baz():
    time.sleep(1)
    time.sleep(2)
    return 1
baz()

bazRAN 5 keer en drukde dit:

        20 function calls in 15.003 seconds
   Ordered by: internal time
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       10   15.003    1.500   15.003    1.500 {built-in method time.sleep}
        5    0.000    0.000   15.003    3.001 <ipython-input-9-c89afe010372>:3(baz)
        5    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

Specificeren van de hoeveelheid keren

@cumulative_profiler(3)
def baz():
    ...

18

CProfile is geweldig voor snelle profilering, maar meestal eindigde het voor mij met de fouten. Functie Runctx lost dit probleem op door de omgeving en variabelen correct te initialiseren, hoop dat het nuttig kan zijn voor iemand:

import cProfile
cProfile.runctx('foo()', None, locals())

19

Mijn manier is om yappi te gebruiken (https://github.com/sumerc/yappi) . Het is vooral handig in combinatie met een RPC-server waar (zelfs alleen voor debuggen) u een methode registreert om profielinformatie te starten, stoppen en afdrukken, b.v. op deze manier:

@staticmethod
def startProfiler():
    yappi.start()
@staticmethod
def stopProfiler():
    yappi.stop()
@staticmethod
def printProfiler():
    stats = yappi.get_stats(yappi.SORTTYPE_TTOT, yappi.SORTORDER_DESC, 20)
    statPrint = '\n'
    namesArr = [len(str(stat[0])) for stat in stats.func_stats]
    log.debug("namesArr %s", str(namesArr))
    maxNameLen = max(namesArr)
    log.debug("maxNameLen: %s", maxNameLen)
    for stat in stats.func_stats:
        nameAppendSpaces = [' ' for i in range(maxNameLen - len(stat[0]))]
        log.debug('nameAppendSpaces: %s', nameAppendSpaces)
        blankSpace = ''
        for space in nameAppendSpaces:
            blankSpace += space
        log.debug("adding spaces: %s", len(nameAppendSpaces))
        statPrint = statPrint + str(stat[0]) + blankSpace + " " + str(stat[1]).ljust(8) + "\t" + str(
            round(stat[2], 2)).ljust(8 - len(str(stat[2]))) + "\t" + str(round(stat[3], 2)) + "\n"
    log.log(1000, "\nname" + ''.ljust(maxNameLen - 4) + " ncall \tttot \ttsub")
    log.log(1000, statPrint)

Als uw programma werkt, kunt u de profiler op elk moment starten door de RPC-methode startProfileraan te roepen en profileringsinformatie naar een logbestand te dumpen door printProfileraan te roepen (of de rpc-methode om het terug te sturen naar de beller) en dergelijke uitvoer te krijgen:

2014-02-19 16:32:24,128-|SVR-MAIN  |-(Thread-3   )-Level 1000: 
name                                                                                                                                      ncall     ttot    tsub
2014-02-19 16:32:24,128-|SVR-MAIN  |-(Thread-3   )-Level 1000: 
C:\Python27\lib\sched.py.run:80                                                                                                           22        0.11    0.05
M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\pyAheadRpcSrv\xmlRpc.py.iterFnc:293                                                22        0.11    0.0
M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\serverMain.py.makeIteration:515                                                    22        0.11    0.0
M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\pyAheadRpcSrv\PicklingXMLRPC.py._dispatch:66                                       1         0.0     0.0
C:\Python27\lib\BaseHTTPServer.py.date_time_string:464                                                                                    1         0.0     0.0
c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\_psmswindows.py._get_raw_meminfo:243     4         0.0     0.0
C:\Python27\lib\SimpleXMLRPCServer.py.decode_request_content:537                                                                          1         0.0     0.0
c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\_psmswindows.py.get_system_cpu_times:148 4         0.0     0.0
<string>.__new__:8                                                                                                                        220       0.0     0.0
C:\Python27\lib\socket.py.close:276                                                                                                       4         0.0     0.0
C:\Python27\lib\threading.py.__init__:558                                                                                                 1         0.0     0.0
<string>.__new__:8                                                                                                                        4         0.0     0.0
C:\Python27\lib\threading.py.notify:372                                                                                                   1         0.0     0.0
C:\Python27\lib\rfc822.py.getheader:285                                                                                                   4         0.0     0.0
C:\Python27\lib\BaseHTTPServer.py.handle_one_request:301                                                                                  1         0.0     0.0
C:\Python27\lib\xmlrpclib.py.end:816                                                                                                      3         0.0     0.0
C:\Python27\lib\SimpleXMLRPCServer.py.do_POST:467                                                                                         1         0.0     0.0
C:\Python27\lib\SimpleXMLRPCServer.py.is_rpc_path_valid:460                                                                               1         0.0     0.0
C:\Python27\lib\SocketServer.py.close_request:475                                                                                         1         0.0     0.0
c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\__init__.py.cpu_times:1066               4         0.0     0.0 

Het is misschien niet erg handig voor korte scripts, maar helpt bij het optimaliseren van processen van het servertype, vooral gezien de printProfiler-methode in de loop van de tijd meerdere keren kan worden aangeroepen om b.v. verschillende scenario’s voor programmagebruik.

In nieuwere versies van yappi werkt de volgende code:

@staticmethod
def printProfile():
    yappi.get_func_stats().print_all()

Antwoord 20

gprof2dot_magic

Magische functie voor gprof2dotom elke Python-instructie te profileren als een DOT-grafiek in JupyterLab of Jupyter Notebook.

GitHub-opslagplaats: https://github.com/mattijn/gprof2dot_magic

installatie

Zorg ervoor dat je het Python-pakket gprof2dot_magichebt.

pip install gprof2dot_magic

De afhankelijkheden gprof2doten graphvizworden ook geïnstalleerd

gebruik

Om de magische functie in te schakelen, laadt u eerst de gprof2dot_magicmodule

%load_ext gprof2dot_magic

en profileer vervolgens elke regel als een DOT-grafiek als zodanig:

%gprof2dot print('hello world')


Antwoord 21

Voor snelle profielstatistieken op een IPython-notebook.
Men kan line_profileren memory_profilerrechtstreeks in hun notebooks insluiten.

Nog een nuttig pakket is pympler . Het is een krachtig profilerspakket dat in staat is om klassen, objecten, functies, geheugenlekken enz. Voorbeelden hieronder, documenten bijgevoegd.

Haal het!

!pip install line_profiler
!pip install memory_profiler
!pip install pympler

Laad het!

%load_ext line_profiler
%load_ext memory_profiler

Gebruik het!


% tijd

%time print('Outputs CPU time,Wall Clock time') 
#CPU times: user 2 µs, sys: 0 ns, total: 2 µs Wall time: 5.96 µs

geeft:

  • CPU-tijden: CPU-niveau uitvoeringstijd
  • Sys-tijden: executietijd van het systeemniveau
  • Totaal: CPU-tijd + systeemtijd
  • Wandduur: wandkloktijd

% timeit

%timeit -r 7 -n 1000 print('Outputs execution time of the snippet') 
#1000 loops, best of 7: 7.46 ns per loop
  • geeft de beste time-up van het gegeven aantal runs (R) in Looping (N) -tijden.
  • Uitgangen Details op System Caching:
    • Wanneer codefragmenten meerdere keren worden uitgevoerd, caches systeem een ​​paar oparaties en voert ze niet opnieuw uit die de nauwkeurigheid van de profielrapporten kan belemmeren.

% PROUN

%prun -s cumulative 'Code to profile' 

geeft:

  • Aantal functies oproepen (ncalls)
  • heeft inzendingen per functie-oproep (DIFINICT)
  • Tijd genomen per gesprek (percall)
  • tijd verstreken tot die functie-oproep (cumtime)
  • naam van de functie/module genaamd etc…


%memit

%memit 'Code to profile'
#peak memory: 199.45 MiB, increment: 0.00 MiB

Geeft:

  • Geheugengebruik

%lprun

#Example function
def fun():
  for i in range(10):
    print(i)
#Usage: %lprun <name_of_the_function> function
%lprun -f fun fun()

Geeft:

  • Lijngewijze statistieken


sys.getsizeof

sys.getsizeof('code to profile')
# 64 bytes

Retourneert de grootte van een object in bytes.


asizeof() van pympler

from pympler import asizeof
obj = [1,2,("hey","ha"),3]
print(asizeof.asizeof(obj,stats=4))

pympler.asizeof kan worden gebruikt om te onderzoeken hoeveel geheugen bepaalde Python-objecten verbruiken.
In tegenstelling tot sys.getsizeof, past asizeof objecten recursief aan


tracker van pympler

from pympler import tracker
tr = tracker.SummaryTracker()
def fun():
  li = [1,2,3]
  di = {"ha":"haha","duh":"Umm"}
fun()
tr.print_diff()

volgt de levensduur van een functie.

Pympler-pakket bestaat uit een enorm aantal high-utility-functies op profielcode. Die hier niet kunnen worden gedekt. Zie de documentatie die is bijgevoegd voor uitgebreide profielimplementaties.

Pympler DOC


22

Onlangs heb ik een plug-in gemaakt voor Pycharm waarmee je de resultaten van line_profilerin de Pycharm-editor gemakkelijk kunt analyseren en visualiseren.

line_profileris ook vermeld in andere antwoorden en is een geweldige tool om precies te analyseren hoeveel tijd wordt besteed door de Python-tolk in bepaalde lijnen.

De Pycharm-plug-in die ik heb gemaakt, is hier te vinden:
https://plugins.jetbrains.com/plugin/16536-line-profiler

Het heeft een helperpakket nodig in uw Python-omgeving genaamd line-profiler-pycharmdie kan worden geïnstalleerd met PIP of via de plug-in zelf.

Na het installeren van de plug-in in Pycharm:

  1. Versier elke functie die u wilt profileren met de line_profiler_pycharm.profiledecorator
  2. Werk met de runner ‘Profiellijnen

Screenshot van resultaten:


23

Om toe te voegen aan https://stackoverflow.com/a/582337/1070617 ,

Ik heb deze module geschreven waarmee u CProfile kunt gebruiken en de uitvoer eenvoudig kunt bekijken. Meer hier: https://github.com/ymichael/cprofilev

$ python -m cprofilev /your/python/program
# Go to http://localhost:4000 to view collected statistics.

Zie ook: http://ymichael.com/ 2014 / 03/08 / Profilering-Python-with-CProfile.html over het begrijpen van de verzamelde statistieken.


24

Het zou afhangen van wat u uit de profilering wilt zien. Eenvoudige tijd
Metrics kunnen worden gegeven door (bash).

time python python_prog.py

Zelfs ‘/ usr / bin / time’ kan gedetailleerde statistieken uitvoeren met behulp van ‘–verbose’ vlag.

Om de tijdstatistieken van elke functie te controleren en om beter te begrijpen hoeveel tijd wordt besteed aan functies, kunt u de ingebouwde CProfile in Python gebruiken.

Naar meer gedetailleerde statistieken zoals prestaties, is de tijd niet de enige metriek. Je kunt je zorgen maken over geheugen, draden enz.
Profilering opties:
1. Line_Profiler is een andere profiler die gewoonlijk wordt gebruikt om de timingstatistiekenlijn te vinden.
2. Memory_Profiler is een hulpmiddel om geheugengebruik te profileren.
3. hopy (van project guppy) Profiel Hoe objecten in de hoop worden gebruikt.

Dit zijn enkele van de gemeenschappelijke die ik heb gebruikt om te gebruiken. Maar als je meer wilt weten, probeer dan dit boek
Het is een redelijk goed boek over het starten met prestaties in gedachten. U kunt doorgaan naar geavanceerde onderwerpen bij het gebruik van Cython en JIT (Just-In-Time) Compiled Python.


25

Ik heb net mijn eigen profiler ontwikkeld geïnspireerd op pypref_time:

https://github.com/modaresimr/auto_profiler

Door een decorateur toe te voegen, toont het een boom met tijdrovende functies

@Profiler(depth=4, on_disable=show)

Install by: pip install auto_profiler

Voorbeeld

import time # line number 1
import random
from auto_profiler import Profiler, Tree
def f1():
    mysleep(.6+random.random())
def mysleep(t):
    time.sleep(t)
def fact(i):
    f1()
    if(i==1):
        return 1
    return i*fact(i-1)
def show(p):
    print('Time   [Hits * PerHit] Function name [Called from] [Function Location]\n'+\
          '-----------------------------------------------------------------------')
    print(Tree(p.root, threshold=0.5))
@Profiler(depth=4, on_disable=show)
def main():
    for i in range(5):
        f1()
    fact(3)
if __name__ == '__main__':
    main()

Voorbeelduitvoer


Time   [Hits * PerHit] Function name [Called from] [function location]
-----------------------------------------------------------------------
8.974s [1 * 8.974]  main  [auto-profiler/profiler.py:267]  [/test/t2.py:30]
├── 5.954s [5 * 1.191]  f1  [/test/t2.py:34]  [/test/t2.py:14]
│   └── 5.954s [5 * 1.191]  mysleep  [/test/t2.py:15]  [/test/t2.py:17]
│       └── 5.954s [5 * 1.191]  <time.sleep>
|
|
|   # The rest is for the example recursive function call fact
└── 3.020s [1 * 3.020]  fact  [/test/t2.py:36]  [/test/t2.py:20]
    ├── 0.849s [1 * 0.849]  f1  [/test/t2.py:21]  [/test/t2.py:14]
    │   └── 0.849s [1 * 0.849]  mysleep  [/test/t2.py:15]  [/test/t2.py:17]
    │       └── 0.849s [1 * 0.849]  <time.sleep>
    └── 2.171s [1 * 2.171]  fact  [/test/t2.py:24]  [/test/t2.py:20]
        ├── 1.552s [1 * 1.552]  f1  [/test/t2.py:21]  [/test/t2.py:14]
        │   └── 1.552s [1 * 1.552]  mysleep  [/test/t2.py:15]  [/test/t2.py:17]
        └── 0.619s [1 * 0.619]  fact  [/test/t2.py:24]  [/test/t2.py:20]
            └── 0.619s [1 * 0.619]  f1  [/test/t2.py:21]  [/test/t2.py:14]

Antwoord 26

Met een statistische profiler zoals austinis geen instrumentatie vereist, wat betekent dat u profileringsgegevens kunt krijgen uit een Python-toepassing eenvoudig met

austin python3 my_script.py

De onbewerkte uitvoer is niet erg handig, maar je kunt dat doorsturen naar flamegraph.pl
om een vlamgrafiekweergave van die gegevens te krijgen die u een overzicht geeft van waar de tijd (gemeten in microseconden van realtime) wordt doorgebracht.

austin python3 my_script.py | flamegraph.pl > my_script_profile.svg

Als alternatief kunt u ook de webtoepassing Speedscope.appgebruiken voor snelle visualisatie van de verzamelde monsters. Als je pprofhebt geïnstalleerd, kun je ook austin-python(met bijv. pipx install austin-python) en gebruik de austin2pprofom naar het pprof-formaat.


Antwoord 27

Ooit willen weten wat dat pythonscript in godsnaam aan het doen is? Voer de in
Inspecteer Shell. Met Inspect Shell kunt u globals afdrukken/wijzigen en uitvoeren
functies zonder het lopende script te onderbreken. Nu met
automatisch aanvullen en opdrachtgeschiedenis (alleen op linux).

Inspect Shell is geen pdb-achtige debugger.

https://github.com/amoffat/Inspect-Shell

Je zou dat kunnen gebruiken (en je polshorloge).


Antwoord 28

Er is ook een statistische profiler genaamd statprof. Het is een bemonsteringsprofiler, dus het voegt minimale overhead toe aan uw code en geeft op regels gebaseerde (niet alleen op functie gebaseerde) timings. Het is meer geschikt voor zachte real-time toepassingen zoals games, maar is mogelijk minder nauwkeurig dan cProfile.

De versie in pypiis een beetje oud, dus kan deze met pipdoor de git-repositoryop te geven:

pip install git+git://github.com/bos/statprof.py@1a33eba91899afe17a8b752c6dfdec6f05dd0c01

Je kunt het als volgt uitvoeren:

import statprof
with statprof.profile():
    my_questionable_function()

Zie ook https://stackoverflow.com/a/10333592/320036


Antwoord 29

Als ik niet root op de server, gebruik ik
lsprofcalltree.pyen voer mijn programma als volgt uit:

python lsprofcalltree.py -o callgrind.1 test.py

Dan kan ik het rapport openen met elke callgrind-compatibele software, zoals qcachegrind

Other episodes