Ricerca…


Osservazioni

Quando si tenta di migliorare le prestazioni di uno script Python, prima di tutto si dovrebbe essere in grado di trovare il collo di bottiglia del proprio script e notare che nessuna ottimizzazione può compensare una scelta sbagliata nelle strutture dati o un difetto nella progettazione dell'algoritmo. Identificare i colli di bottiglia delle prestazioni può essere fatto profilando il tuo script. In secondo luogo, non cercare di ottimizzare troppo presto il processo di codifica a scapito della leggibilità / design / qualità. Donald Knuth ha rilasciato la seguente dichiarazione sull'ottimizzazione:

"Dovremmo dimenticare le piccole efficienze, diciamo circa il 97% delle volte: l'ottimizzazione prematura è la radice di tutto il male. Tuttavia non dovremmo perdere le nostre opportunità in quel 3% critico ".

Codice di profilazione

Prima di tutto dovresti essere in grado di trovare il collo di bottiglia del tuo script e notare che nessuna ottimizzazione può compensare una scelta sbagliata nella struttura dei dati o un difetto nella progettazione dell'algoritmo. In secondo luogo, non cercare di ottimizzare troppo presto il processo di codifica a scapito della leggibilità / design / qualità. Donald Knuth ha rilasciato la seguente dichiarazione sull'ottimizzazione:

"Dovremmo dimenticare le piccole efficienze, diciamo circa il 97% delle volte: l'ottimizzazione prematura è la radice di tutto il male, ma non dovremmo perdere le nostre opportunità in quel 3% critico"

Per profilare il tuo codice hai diversi strumenti: cProfile (o il profile più lento) dalla libreria standard, line_profiler e timeit . Ognuno di loro ha uno scopo diverso.

cProfile è un profiler deterministico: la funzione chiamata, la funzione di ritorno e gli eventi di eccezione sono monitorati e vengono eseguiti tempi precisi per gli intervalli tra questi eventi (fino a 0,001 s). La documentazione della biblioteca ([ https://docs.python.org/2/library/profile.html][1]) ci fornisce un caso di utilizzo semplice

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

O se preferisci avvolgere parti del tuo codice esistente:

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()

Ciò creerà le uscite come nella tabella sottostante, in cui è possibile vedere rapidamente dove trascorre la maggior parte del tempo il programma e identificare le funzioni da ottimizzare.

         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}

Il modulo line_profiler ([ https://github.com/rkern/line_profiler][1]) è utile per avere un'analisi linea per linea del tuo codice. Questo ovviamente non è gestibile per script lunghi ma è indirizzato a frammenti. Vedi la documentazione per maggiori dettagli. Il modo più semplice per iniziare è usare lo script kernprof come spiegato nella pagina del pacchetto, nota che dovrai specificare manualmente le funzioni del profilo.

$ kernprof -l script_to_profile.py

kernprof creerà un'istanza di LineProfiler e la inserirà nello spazio __builtins__ nomi __builtins__ con il nome del profilo. È stato scritto per essere usato come decoratore, quindi nella sceneggiatura, decori le funzioni che vuoi profilare con @profile .

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

Il comportamento predefinito di kernprof è di mettere i risultati in un file binario script_to_profile.py.lprof . Puoi dire a kernprof di visualizzare immediatamente i risultati formattati sul terminale con l'opzione [-v / - visualizza]. Altrimenti, puoi visualizzare i risultati in un secondo momento in questo modo:

$ python -m line_profiler script_to_profile.py.lprof

Infine timeit fornisce un modo semplice per testare un liner o una piccola espressione sia dalla riga di comando che dalla shell python. Questo modulo risponderà a domande come, è più veloce fare una comprensione di lista o usare la list() built-in list() quando si trasforma un set in una lista. Cerca la parola chiave setup o -s per aggiungere il codice di configurazione.

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

da un terminale

$ 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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow