Ostatnio zainteresowałem się algorytmami i zacząłem je badać, pisząc naiwną implementację, a następnie optymalizując ją na różne sposoby.
Znam już standardowy moduł Pythona do profilowania środowiska wykonawczego (dla większości rzeczy uważam, że funkcja timeit magic w IPython jest wystarczająca), ale interesuje mnie również użycie pamięci, więc mogę również zbadać te kompromisy ( np. koszt buforowania tabeli wcześniej obliczonych wartości w porównaniu do ich ponownego obliczenia w razie potrzeby). Czy jest dla mnie moduł, który profiluje wykorzystanie pamięci przez daną funkcję dla mnie?
Odpowiedzi:
Na ten już odpowiedziano tutaj: profiler pamięci Python
Zasadniczo robisz coś takiego (cytowany z Guppy-PE ):
źródło
Python 3.4 zawiera nowy moduł:
tracemalloc
. Zapewnia szczegółowe statystyki dotyczące tego, który kod przydziela najwięcej pamięci. Oto przykład, który wyświetla trzy górne wiersze przydzielające pamięć.A oto wyniki:
Kiedy wyciek pamięci nie jest wyciek?
Ten przykład jest świetny, gdy pamięć jest nadal przechowywana na końcu obliczeń, ale czasami masz kod, który przydziela dużo pamięci, a następnie ją zwalnia. Technicznie nie jest to wyciek pamięci, ale zużywa więcej pamięci, niż myślisz. Jak możesz śledzić zużycie pamięci, gdy wszystko zostanie zwolnione? Jeśli to Twój kod, prawdopodobnie możesz dodać kod do debugowania, aby robić migawki podczas jego działania. Jeśli nie, możesz uruchomić wątek w tle, aby monitorować użycie pamięci podczas działania głównego wątku.
Oto poprzedni przykład, w którym kod został przeniesiony do
count_prefixes()
funkcji. Gdy funkcja ta powróci, cała pamięć zostanie zwolniona. Dodałem także kilkasleep()
połączeń, aby zasymulować długotrwałe obliczenia.Kiedy uruchamiam tę wersję, zużycie pamięci spadło z 6 MB do 4KB, ponieważ funkcja zwolniła całą swoją pamięć po zakończeniu.
Oto wersja inspirowana inną odpowiedzią, która rozpoczyna drugi wątek w celu monitorowania zużycia pamięci.
resource
Moduł pozwala sprawdzić bieżące wykorzystanie pamięci i zapisać zrzut z wykorzystaniem pamięci szczyt. Kolejka pozwala wątkowi głównemu powiedzieć wątkowi monitora pamięci, kiedy wydrukować raport i zamknąć. Po uruchomieniu pokazuje pamięć używaną przezlist()
połączenie:Jeśli korzystasz z systemu Linux, może okazać się
/proc/self/statm
bardziej przydatny niżresource
moduł.źródło
long_running()
Wewnątrzcount_prefixes()
funkcji, maksymalne wartości RSS nie zostaną wydrukowane, dopóki nielong_running()
powróci. Czy się mylę?memory_monitor()
działa w osobnym wątkucount_prefixes()
, więc jedynym sposobem, w jaki można wpłynąć na inny, jest GIL i kolejka komunikatów, do której przekazujęmemory_monitor()
. Podejrzewam, że podczascount_prefixes()
połączeńsleep()
zachęca kontekst wątków do zmiany. Jeślilong_running()
tak naprawdę nie trwa to długo, kontekst wątku może się nie przełączyć, dopóki niesleep()
oddzwoniszcount_prefixes()
. Jeśli to nie ma sensu, opublikuj nowe pytanie i link do niego stąd.Jeśli chcesz tylko spojrzeć na wykorzystanie pamięci przez obiekt, ( odpowiedz na inne pytanie )
źródło
asizeof
asizeof
może przyczynić się do RSS, tak. Nie jestem pewien, co jeszcze rozumiesz przez „związany z”.tracemalloc
rozwiązanie poniżej wielkości szybciejUjawnienie:
Ale miło ze względu na swoją prostotę:
Po prostu wstaw,
using("Label")
gdzie chcesz zobaczyć, co się dzieje. Na przykładźródło
usage[2]
siebie, patrzyszru_maxrss
, co jest tylko częścią procesu, który jest rezydentem . To niewiele pomoże, jeśli proces został zamieniony na dysk, nawet częściowo.resource
to moduł specyficzny dla Uniksa, który nie działa w systemie Windows.ru_maxrss
(to znaczyusage[2]
) są KB, a nie strony, więc nie ma potrzeby pomnożenia tej liczby przezresource.getpagesize()
.Ponieważ zaakceptowana odpowiedź, a także kolejna najwyższa głosowana odpowiedź mają, moim zdaniem, pewne problemy, chciałbym zaoferować jeszcze jedną odpowiedź, która jest ściśle oparta na odpowiedzi Ihora B. z niewielkimi, ale istotnymi modyfikacjami.
To rozwiązanie pozwala uruchomić profilowanie albo przez zawinięcie wywołania
profile
funkcji funkcją i wywołanie jej, albo przez dekorowanie funkcji / metody@profile
dekoratorem.Pierwsza technika jest przydatna, gdy chcesz profilować jakiś kod innej firmy bez bałaganu z jego źródłem, podczas gdy druga technika jest nieco „czystsza” i działa lepiej, gdy nie masz nic przeciwko modyfikowaniu źródła funkcji / metody, którą chcesz chcesz profilować.
Zmodyfikowałem również dane wyjściowe, aby uzyskać RSS, VMS i pamięć współdzieloną. Nie dbam o wartości „przed” i „po”, ale tylko o deltę, więc usunąłem je (jeśli porównujesz odpowiedź Ihora B.).
Kod profilujący
Przykładowe użycie, zakładając, że powyższy kod zostanie zapisany jako
profile.py
:To powinno dać wynik podobny do poniższego:
Kilka ważnych uwag końcowych:
profile(my_function, arg)
Profilowaćmy_function(arg)
źródło
Poniżej znajduje się prosty dekorator funkcji, który pozwala śledzić, ile pamięci proces zużył przed wywołaniem funkcji, po wywołaniu funkcji i jaka jest różnica:
Oto mój blog, który opisuje wszystkie szczegóły. ( zarchiwizowany link )
źródło
process.memory_info().rss
nieprocess.get_memory_info().rss
przynajmniej w Ubuntu i pytona 3.6. powiązane stackoverflow.com/questions/41012058/psutil-error-on-macosmoże to pomoże:
< patrz dodatkowe >
źródło
źródło