Jak używać timeit do profilowania kodu Pythona

Z założenia Python przed wydajnością stawia wygodę, czytelność i łatwość użycia. Ale to nie znaczy, że powinieneś zadowalać się powolnym kodem w Pythonie. Prawdopodobnie jest coś, co możesz zrobić, aby to przyspieszyć.

Spośród dostępnych narzędzi do profilowania wydajności kodu w Pythonie najprostszym jest timeitmoduł. timeitsłuży do pomiaru szybkości małych fragmentów kodu - kilku wierszy, funkcji - wykonując kod tysiące, a nawet miliony razy i raportując, ile czasu zajęło wykonanie tych operacji.

timeitjest najbardziej przydatny do porównywania dwóch lub trzech różnych sposobów zrobienia czegoś i sprawdzania, który jest najszybszy. Na przykład pętla, która działa przez tysiące iteracji, jest częstym wąskim gardłem Pythona. Jeśli znajdziesz sposób na przyspieszenie implementacji tej pętli - powiedzmy, używając wbudowanych funkcji Pythona zamiast odręcznego kodu - możesz uzyskać wymierną poprawę wydajności.

Prosty przykład czasu w Pythonie

Oto prosty przykład, jak to timeitdziała:

def f1 (): for n in range (100): pass def f2 (): n = 0 while n <100: n + = 1 if __name__ == "__main__": import timeit print (timeit.timeit (f1, number = 100000)) print (timeit.timeit (f2, liczba = 100000)) 

Ten program porównuje wydajność dwóch sposobów wykonywania iteracji przez pętlę 100 razy: za pomocą wbudowanej range funkcji języka Python  ( f1) i przez zwiększenie wartości zmiennej ( f2). timeit uruchamia każde z tych podejść 100 000 razy i zapewnia całkowity czas wykonywania na koniec każdego z nich. Domyślnie  timeit używa miliona przebiegów, ale ten przykład pokazuje, jak ustawić liczbę przebiegów na dowolną liczbę, która wydaje się odpowiednia.

Wyniki (z procesora Intel i7-3770K):

0,1252315

0.45453989999999994

Oczywiście  range podejście jest znacznie szybsze, o współczynnik około 3,75. Nie jest to zaskakujące; użycie wbudowanego języka Python zazwyczaj daje lepszą wydajność niż ręczne manipulowanie obiektami Pythona.

Użyj Pythona timeit, przekazując ciąg

Innym sposobem użycia  timeit jest przekazanie ciągu, który jest oceniany jako program w Pythonie:

import timeit

print (timeit.timeit ('for n in range (100): pass'))

Można to również zrobić z wiersza poleceń:

python -m timeit "for n in range (100): pass"

Ogólnie rzecz biorąc, łatwiej jest zastosować technikę pokazaną powyżej, ponieważ nie musisz niezręcznie wbijać kodu w łańcuch tekstowy.

Porady dotyczące czasu w Pythonie

Tak przydatne, jak  timeit to możliwe, pamiętaj o tych zastrzeżeniach dotyczących korzystania z niego.

Unikaj używania timeit do profilowania całego programu

Nic nie mówi, że nie możesz  określić  czasu całego programu  timeit. Na przykład prosty 10-liniowy skrypt nie jest złym kandydatem do takiego profilowania.

Ale są lepsze narzędzia do tego zadania - na przykład cProfile moduł Pythona  , który generuje znacznie bardziej szczegółowe statystyki dotyczące wydajności całego programu. timeit działa najlepiej z pojedynczym komponentem lub fragmentem kodu - znowu funkcją lub kilkoma wierszami kodu. Cokolwiek więcej niż to zwykle generuje wyniki, które są zbyt hałaśliwe i niespójne, aby dostarczyć jakichkolwiek znaczących informacji o wydajności.

Ponadto, jeśli program, który profilujesz, zajmuje wiele minut,  timeit nie będzie zbyt użyteczny. Po pierwsze, wykonanie kodu więcej niż kilka razy zajmie zbyt dużo czasu, więc zebrane czasy będą bardzo zgrubne. Po drugie, inne narzędzia są lepiej dostosowane do tego zadania.

Wykonuj wiele operacji na różnych komputerach

Programy nie działają za każdym razem z tą samą prędkością. Współczesne środowiska komputerowe wprowadzają wiele niepewności - rywalizacja z innymi programami o zasoby, zachowanie pamięci podręcznej, planowanie itd. timeit próbuje to zrekompensować, wykonując kod w nieskończoność, ale nadal dobrym pomysłem jest zagregowanie wielu prób. Powinieneś timeit wielokrotnie uruchamiać  profil, wyrzucać najgorsze i najlepsze wyniki, a resztę uśredniać.

Wreszcie, pomaga również przeprowadzić ten sam test na różnych systemach: jak zachowa się coś związanego z dyskiem na dysku SSD w porównaniu z konwencjonalnym wirującym dyskiem twardym? Jak w przypadku każdego innego pytania o wydajność - nie zgaduj, testuj.