Project Euler i inne konkursy kodowania często mają maksymalny czas do uruchomienia lub ludzie chwalą się szybkością działania danego rozwiązania. W Pythonie czasami podejścia są nieco kludgey - tj. Dodawanie kodu czasowego do __main__
.
W jaki sposób można profilować, ile czasu zajmuje uruchomienie programu w języku Python?
python
performance
profiling
time-complexity
Chris Lawlor
źródło
źródło
Odpowiedzi:
Python zawiera profiler o nazwie cProfile . Podaje nie tylko całkowity czas działania, ale także czasy każdej funkcji osobno i informuje, ile razy każda funkcja została wywołana, co ułatwia określenie, gdzie należy dokonać optymalizacji.
Możesz go wywołać z poziomu kodu lub z interpretera:
Jeszcze bardziej przydatne, możesz uruchomić cProfile podczas uruchamiania skryptu:
Aby było to jeszcze łatwiejsze, stworzyłem mały plik wsadowy o nazwie „profile.bat”:
Więc wszystko, co muszę zrobić, to uruchomić:
I dostaję to:
EDYCJA: Zaktualizowano link do dobrego zasobu wideo z PyCon 2013 zatytułowanego Profilowanie w języku Python
Także przez YouTube .
źródło
python -m cProfile -o <out.profile> <script>
) RunSnakeRun , wywoływany jakorunsnake <out.profile>
jest nieoceniony.cprofile
nadal zaleca sięprofile
.Jakiś czas temu zrobiłem,
pycallgraph
który generuje wizualizację z twojego kodu Python. Edycja: Zaktualizowałem przykład do pracy z 3.3, najnowszą wersją od tego pisania.Po
pip install pycallgraph
zainstalowaniu GraphViz możesz uruchomić go z wiersza poleceń:Możesz także profilować określone części kodu:
Każdy z nich wygeneruje
pycallgraph.png
plik podobny do poniższego obrazu:źródło
Traceback (most recent call last): /pycallgraph.py", line 90, in generate output.done() File "/net_downloaded/pycallgraph-develop/pycallgraph/output/graphviz.py", line 94, in done source = self.generate() File "/net_downloaded/pycallgraph-develop/pycallgraph/output/graphviz.py", line 143, in generate indent_join.join(self.generate_attributes()), File "/net_downloaded/pycallgraph-develop/pycallgraph/output/graphviz.py", line 169, in generate_attributes section, self.attrs_from_dict(attrs), ValueError: zero length field name in format
sudo apt-get install graphviz
.Warto zauważyć, że korzystanie z profilera działa (domyślnie) tylko w głównym wątku i nie uzyskasz żadnych informacji z innych wątków, jeśli ich użyjesz. Może to być trochę kłopotliwe, ponieważ jest to całkowicie nie wspomniane w dokumentacji profilera .
Jeśli chcesz także profilować wątki, spójrz na
threading.setprofile()
funkcję w dokumentach.Możesz również utworzyć własną
threading.Thread
podklasę, aby to zrobić:i użyj tej
ProfiledThread
klasy zamiast standardowej. Może dać ci większą elastyczność, ale nie jestem pewien, czy warto, szczególnie jeśli używasz kodu innej firmy, który nie używałby twojej klasy.źródło
target
, która jest wykonywana przez tothreading.Thread.run()
wywołanie. Ale jak powiedziałem w odpowiedzi, prawdopodobnie nie warto podklasować wątku, ponieważ żaden kod innej firmy nie użyje go, a zamiast tego użyjethreading.setprofile()
.Python wiki to świetna strona do profilowania zasobów: http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code
podobnie jak dokumentacja Pythona: http://docs.python.org/library/profile.html
jak pokazuje Chris Lawlor cProfile to świetne narzędzie, które można łatwo wykorzystać do drukowania na ekranie:
lub złożyć:
PS> Jeśli używasz Ubuntu, pamiętaj o zainstalowaniu profilu python
Jeśli wyprowadzasz dane do pliku, możesz uzyskać ładne wizualizacje za pomocą następujących narzędzi
PyCallGraph: narzędzie do tworzenia
instalacji grafów połączeń :
biegać:
widok:
Możesz użyć, co chcesz, aby wyświetlić plik png, użyłem gimp
Niestety często dostaję
kropka: wykres jest za duży dla map bitowych renderera Cairo. Skalowanie o 0,257079 w celu dopasowania
co sprawia, że moje obrazy są wyjątkowo małe. Generalnie tworzę pliki svg:
PS> upewnij się, że zainstalowałeś graphviz (który zapewnia program kropkowy):
Alternatywne wykresy przy użyciu gprof2dot przez @maxy / @quodlibetor:
źródło
Komentarz @ Maxy'ego do tej odpowiedzi pomógł mi na tyle, że myślę, że zasługuje na swoją własną odpowiedź: miałem już pliki .pstats wygenerowane przez cProfile i nie chciałem ponownie uruchamiać rzeczy z pycallgraph, więc użyłem gprof2dot i zrobiłem się ładny svgs:
i BLAM!
Używa kropki (tej samej, której używa pycallgraph), więc dane wyjściowe wyglądają podobnie. Mam wrażenie, że gprof2dot traci mniej informacji:
źródło
pwd
/gprof2dot/gprof2dot.py $ HOME / bin (lub użyj ln -s $ PWD / gprof2dot / gprof2dot.py ~ / bin w większości powłok - akcent poważny jest traktowany jako formatowanie w pierwszej kolejności wersja).ln
Niemal za każdym razem otrzymuję błędną kolejność argumentów.Podczas badania tego tematu natrafiłem na przydatne narzędzie o nazwie SnakeViz . SnakeViz to internetowe narzędzie do wizualizacji profilowania. Jest bardzo łatwy w instalacji i obsłudze. Zwykle używam go do generowania pliku statystyk
%prun
a następnie analizy w SnakeViz.Główną zastosowaną techniką jest karta Sunburst jak pokazano poniżej, w którym hierarchia wywołań funkcji jest ułożona jako warstwy łuków i informacji o czasie zakodowanych w ich szerokościach kątowych.
Najlepszą rzeczą jest interakcja z tabelą. Na przykład, aby powiększyć, można kliknąć łuk, a łuk i jego potomkowie zostaną powiększeni jako nowy promień słońca, aby wyświetlić więcej szczegółów.
źródło
Najprostszy i najszybszy sposób na znalezienie dokąd zmierza cały czas.
Rysuje wykres kołowy w przeglądarce. Największym elementem jest funkcja problemu. Bardzo prosta.
źródło
Myślę, że
cProfile
jest to świetne do profilowania, a jednocześniekcachegrind
do wizualizacji wyników.pyprof2calltree
Pomiędzy uchwytami konwersja plików.Aby zainstalować wymagane narzędzia (przynajmniej na Ubuntu):
Wynik:
źródło
brew install qcachegrind
i substitude każdakcachegrind
zeqcachegrind
w opisie udanej profilowania.export QT_X11_NO_MITSHM=1
Warto również wspomnieć o przeglądarce Run zrzutów graficznych cProfile GUI RunSnakeRun . Pozwala sortować i wybierać, przybliżając odpowiednie części programu. Rozmiary prostokątów na zdjęciu są proporcjonalne do czasu. Jeśli najedziesz myszką na prostokąt, podświetli to wywołanie w tabeli i wszędzie na mapie. Dwukrotne kliknięcie prostokąta powoduje powiększenie tej części. Pokaże ci, kto wywołuje tę część i co ta część wzywa.
Informacje opisowe są bardzo pomocne. Pokazuje kod tego bitu, który może być pomocny w przypadku wywołań wbudowanej biblioteki. Mówi ci, jaki plik i jaką linię znaleźć kod.
Chciałbym również wskazać, że PO powiedział „profilowanie”, ale wygląda na to, że miał na myśli „timing”. Pamiętaj, że programy będą działały wolniej podczas profilowania.
źródło
Ładnym modułem profilującym jest line_profiler (wywoływany za pomocą skryptu kernprof.py). Można go pobrać tutaj .
Rozumiem, że cProfile podaje tylko informacje o całkowitym czasie spędzonym na każdej funkcji. Poszczególne wiersze kodu nie są taktowane. Jest to problem w informatyce naukowej, ponieważ często jedna linia może zająć dużo czasu. Ponadto, jak pamiętam, cProfile nie złapał czasu, który spędziłem na powiedzmy numpy.dot.
źródło
Niedawno stworzyłem tuńczyka do wizualizacji środowiska wykonawczego Python i importowania profili; może to być pomocne tutaj.
Zainstaluj za pomocą
Utwórz profil środowiska wykonawczego
lub profil importu (wymagany Python 3.7+)
Następnie po prostu uruchom tuńczyka na pliku
źródło
pprofile
line_profiler
(już tutaj zaprezentowane) również zainspirowanepprofile
, co opisano jako:Zapewnia ziarnistość linii, ponieważ
line_profiler
jest czystym Pythonem, może być używany jako samodzielna komenda lub moduł, a nawet może generować pliki w formacie callgrind, które można łatwo analizować[k|q]cachegrind
.vprof
Istnieje również vprof , pakiet Python opisany jako:
źródło
Istnieje wiele świetnych odpowiedzi, ale albo używają wiersza polecenia, albo zewnętrznego programu do profilowania i / lub sortowania wyników.
Naprawdę brakowało mi sposobu, w jaki mógłbym użyć w swoim IDE (eclipse-PyDev) bez dotykania wiersza poleceń lub instalowania czegokolwiek. Więc oto jest.
Profilowanie bez wiersza poleceń
Aby uzyskać więcej informacji, zobacz dokumenty lub inne odpowiedzi.
źródło
Po odpowiedzi Joe Shawa, że kod wielowątkowy nie działa zgodnie z oczekiwaniami, doszedłem do wniosku, że
runcall
metoda w cProfile po prostu działaself.enable()
iself.disable()
wywołuje profilowane wywołanie funkcji, więc możesz po prostu zrobić to sam i mieć dowolny kod pomiędzy nimi minimalna ingerencja w istniejący kod.źródło
cprofile.py
kod źródłowy ujawnia, że właśnie toruncall()
działa. Mówiąc dokładniej, po utworzeniu instancji profilu za pomocąprof = cprofile.Profile()
, natychmiast wywołujeprof.disable()
, a następnie dodajeprof.enable()
iprof.disable()
wywołuje sekcję kodu, który chcesz profilować.W Virtaal za źródło jest bardzo przydatna klasa i dekorator, który może wnieść do profilowania (nawet dla konkretnych metod / funkcji) bardzo łatwe. Dane wyjściowe można następnie bardzo wygodnie przeglądać w KCacheGrind.
źródło
cProfile jest świetny do szybkiego profilowania, ale przez większość czasu kończyło się to z błędami. Funkcja runctx rozwiązuje ten problem, poprawnie inicjując środowisko i zmienne. Mam nadzieję, że może się przydać komuś:
źródło
Jeśli chcesz utworzyć skumulowany profiler, co oznacza uruchomienie funkcji kilka razy z rzędu i obejrzenie sumy wyników.
możesz użyć tego
cumulative_profiler
dekoratora:jest specyficzny dla python> = 3.6, ale możesz go usunąć,
nonlocal
aby działał na starszych wersjach.Przykład
profilowanie funkcji
baz
baz
pobiegł 5 razy i wydrukował to:określając ilość razy
źródło
Rozwiązanie tylko dla terminali (i najprostsze), na wypadek, gdyby wszystkie te fantazyjne interfejsy użytkownika nie instalowały się lub nie działały: całkowicie
zignoruj
cProfile
i zamień napyinstrument
, które będą zbierać i wyświetlać drzewo wywołań zaraz po wykonaniu.Zainstalować:
Profil i wynik wyświetlania:
Działa z python2 i 3.
[EDYCJA] Dokumentacja API do profilowania tylko części kodu można znaleźć tutaj .
źródło
Moim sposobem jest użycie yappi ( https://github.com/sumerc/yappi ). Jest to szczególnie przydatne w połączeniu z serwerem RPC, w którym (nawet tylko w celu debugowania) rejestrujesz metodę uruchamiania, zatrzymywania i drukowania informacji profilowania, np. W ten sposób:
Następnie, gdy twój program działa, możesz uruchomić
startProfiler
profilowanie w dowolnym momencie, wywołując metodę RPC i zrzucić informacje profilowania do pliku dziennika, wywołującprintProfiler
(lub zmodyfikuj metodę rpc, aby zwrócić ją do programu wywołującego) i uzyskać takie dane wyjściowe:Może to nie być bardzo przydatne w przypadku krótkich skryptów, ale pomaga zoptymalizować procesy typu serwerowego, szczególnie biorąc pod uwagę, że
printProfiler
metoda może być wywoływana wiele razy w czasie w celu profilowania i porównania np. Różnych scenariuszy użycia programu.W nowszych wersjach yappi działa następujący kod:
źródło
def printProfiler(): if not yappi_available: return stats = yappi.get_func_stats() stats.print_all(columns={0:("name",90), 1:("ncall", 5), 2:("tsub", 8), 3:("ttot", 8), 4:("tavg",8)})
(OK po kilkakrotnym włożeniu bloku kodu do komentarza, którego zrezygnowałem. Jest to niewiarygodnie trudne dla strony z pytaniami i zadaniami programowymi. )Nowym narzędziem do obsługi profilowania w Pythonie jest PyVmMonitor: http://www.pyvmmonitor.com/
Ma kilka unikalnych funkcji, takich jak
Uwaga: jest komercyjny, ale darmowy dla open source.
źródło
gprof2dot_magic
Magiczna funkcja
gprof2dot
do profilowania dowolnej instrukcji Python jako wykresu DOT w JupyterLab lub Jupyter Notebook.Repozytorium GitHub: https://github.com/mattijn/gprof2dot_magic
instalacja
Upewnij się, że masz pakiet Python
gprof2dot_magic
.Jego zależności
gprof2dot
równieżgraphviz
zostaną zainstalowanestosowanie
Aby włączyć funkcję magiczną, najpierw załaduj
gprof2dot_magic
moduła następnie profilować dowolną instrukcję liniową jako wykres DOT jako taki:
źródło
https://github.com/amoffat/Inspect-Shell
Możesz użyć tego (i swojego zegarka).
źródło
Aby dodać do https://stackoverflow.com/a/582337/1070617 ,
Napisałem ten moduł, który pozwala na korzystanie z cProfile i łatwe przeglądanie jego wyników. Więcej tutaj: https://github.com/ymichael/cprofilev
Zobacz także: http://ymichael.com/2014/03/08/profiling-python-with-cprofile.html o tym, jak zrozumieć zebrane statystyki.
źródło
Zależy to od tego, co chcesz zobaczyć w profilowaniu. Proste pomiary czasu mogą być podane przez (bash).
Nawet „/ usr / bin / time” może generować szczegółowe metryki przy użyciu flagi „--verbose”.
Aby sprawdzić metryki czasu podane przez każdą funkcję i lepiej zrozumieć, ile czasu spędza się na funkcjach, możesz użyć wbudowanego cProfile w pythonie.
Przechodząc do bardziej szczegółowych wskaźników, takich jak skuteczność, czas nie jest jedyną miarą. Możesz martwić się pamięcią, wątkami itp.
Opcje profilowania:
1. line_profiler to kolejny profiler używany powszechnie do wyszukiwania metryk synchronizacji linia po linii.
2. memory_profiler to narzędzie do profilowania użycia pamięci.
3. heapy (z projektu Guppy) Profil, w jaki sposób wykorzystywane są obiekty w stercie.
Są to niektóre z typowych, których używam. Ale jeśli chcesz dowiedzieć się więcej, spróbuj przeczytać tę książkę. Jest to całkiem dobra książka na temat rozpoczynania pracy z myślą o wydajności. Możesz przejść do zaawansowanych tematów dotyczących używania Pythona skompilowanego Cython i JIT (Just-in-time).
źródło
Dzięki profilerowi statystycznemu, takiemu jak austin , nie jest wymagana żadna instrumentacja, co oznacza, że dane profilowania można uzyskać z aplikacji Python po prostu za pomocą
Dane wyjściowe surowe nie są zbyt przydatne, ale możesz przesłać je do flamegraph.pl, aby uzyskać graficzną reprezentację tych danych, która daje podział na to, gdzie czas (mierzony w mikrosekundach czasu rzeczywistego) jest spędzany.
źródło
Istnieje również profiler statystyczny o nazwie
statprof
. Jest to profiler do próbkowania, więc dodaje minimalny narzut do twojego kodu i zapewnia czasy taktowania oparte na linii (nie tylko funkcji). Jest bardziej odpowiedni dla miękkich aplikacji w czasie rzeczywistym, takich jak gry, ale może być mniej precyzyjny niż cProfile.Wersja PyPI jest nieco stary, więc można go zainstalować z
pip
określając GIT repozytorium :Możesz uruchomić go w następujący sposób:
Zobacz także https://stackoverflow.com/a/10333592/320036
źródło
Właśnie opracowałem własny profiler zainspirowany pypref_time:
https://github.com/modaresimr/auto_profiler
Dodanie dekoratora spowoduje wyświetlenie drzewa czasochłonnych funkcji
@Profiler(depth=4, on_disable=show)
Przykład
Przykładowy wynik
źródło
Kiedy nie jestem rootem na serwerze, używam lsprofcalltree.py i uruchamiam mój program w następujący sposób:
Następnie mogę otworzyć raport za pomocą dowolnego oprogramowania zgodnego z callgrind, takiego jak qcachegrind
źródło
Aby uzyskać szybkie statystyki profilu dla fragmentów kodu w notatniku IPython. Można osadzić line_profiler i memory_profiler bezpośrednio w swoich notatnikach.
Zdobyć!
Załaduj To!
Użyj tego!
%czas
Daje:
% timeit
% przycinania
Daje:
% memit
Daje:
% lprun
Daje:
źródło