Sök…


Anmärkningar

När du försöker förbättra prestandan för ett Python-skript bör du först och främst kunna hitta flaskhalsen i ditt skript och notera att ingen optimering kan kompensera för ett dåligt val i datastrukturer eller en fel i din algoritmdesign. Identifiera prestandaflaskhalsar kan göras genom att profilera ditt skript. För det andra, försök inte optimera för tidigt i din kodningsprocess på bekostnad av läsbarhet / design / kvalitet. Donald Knuth uttalade följande om optimering:

”Vi borde glömma från små effektiviteter, säga cirka 97% av tiden: för tidig optimering är roten till allt ont. Ändå ska vi inte överlämna våra möjligheter i de kritiska 3%. ”

Kodprofilering

Först och främst bör du kunna hitta flaskhalsen i ditt skript och notera att ingen optimering kan kompensera för ett dåligt val i datastrukturen eller en brist i din algoritmdesign. För det andra, försök inte optimera för tidigt i din kodningsprocess på bekostnad av läsbarhet / design / kvalitet. Donald Knuth uttalade följande om optimering:

"Vi borde glömma från små effektiviteter, säga cirka 97% av tiden: för tidig optimering är roten till allt ont. Men vi bör inte överlämna våra möjligheter i de kritiska 3%."

För att profilera din kod har du flera verktyg: cProfile (eller den långsammare profile ) från standardbiblioteket, line_profiler och timeit . Var och en av dem tjänar ett annat syfte.

cProfile är en determistisk profil: funktionssamtal, funktionsåtergång och undantagshändelser övervakas och exakta tidpunkter görs för intervall mellan dessa händelser (upp till 0,001s). Biblioteksdokumentationen ([ https://docs.python.org/2/library/profile.html????1]) ger oss ett fall med enkel användning

import cProfile
def f(x):
    return "42!"
cProfile.run('f(12)')

Eller om du föredrar att lasta in delar av din befintliga kod:

import cProfile, pstats, StringIO
pr = cProfile.Profile()
pr.enable()
# ... do something ...
# ... long ...
pr.disable()
sortby = 'cumulative'
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats()
print s.getvalue()

Detta skapar utgångar som ser ut som i tabellen nedan, där du snabbt kan se var ditt program tillbringar större delen av sin tid och identifiera de funktioner som ska optimeras.

         3 function calls in 0.000 seconds

Ordered by: standard name
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.000    0.000    0.000    0.000 <stdin>:1(f)
     1    0.000    0.000    0.000    0.000 <string>:1(<module>)
     1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

Modulen line_profiler ([ https://github.com/rkern/line_profiler????1]) är användbar för att ha en rad för radanalys av din kod. Detta är uppenbarligen inte hanterbart för långa skript utan riktar sig till utdrag. Se dokumentationen för mer information. Det enklaste sättet att komma igång är att använda kernprof-skriptet, som förklaras på paketets sida. Observera att du måste ange manuellt funktion (er) för profil.

$ kernprof -l script_to_profile.py

kernprof skapar en instans av LineProfiler och infogar den i __builtins__ namnutrymme med __builtins__ . Det har skrivits för att användas som dekoratör, så i ditt skript dekorerar du de funktioner du vill profilera med @profile .

@profile
def slow_function(a, b, c):
    ...

Standardprocessen för kernprof är att lägga resultaten i en binär fil script_to_profile.py.lprof . Du kan säga kernprof att omedelbart visa de formaterade resultaten vid terminalen med alternativet [-v / - view]. Annars kan du se resultaten senare så:

$ python -m line_profiler script_to_profile.py.lprof

Slutligen ger timeit ett enkelt sätt att testa ett foder eller ett litet uttryck både från kommandoraden och pythonskalet. Den här modulen kommer att besvara frågor som, är det snabbare att göra en listaförståelse eller använda den inbyggda list() när du omvandlar en uppsättning till en lista. Leta efter setup sökord eller -s möjlighet att lägga inställningskoden.

>>> import timeit
>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
0.8187260627746582

från en terminal

$ python -m timeit '"-".join(str(n) for n in range(100))'
10000 loops, best of 3: 40.3 usec per loop


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow