Moja powłoka bash uruchamia się do 3-4 sekund, a jeśli ją uruchomię --norc
, działa natychmiast.
Zacząłem „profilować” /etc/bash.bashrc
i ~/.bashrc
ręcznie wstawiać return
stwierdzenia i szukać ulepszeń szybkości, ale nie jest to proces ilościowy i nie jest wydajny.
Jak mogę profilować moje skrypty bash i sprawdzić, które polecenia uruchamiają się najczęściej?
time bash -c 'exit'
itime bash -i -c 'exit'
, a może grać z--norc
i--noprofile
.Odpowiedzi:
Jeśli masz GNU
date
(lub inną wersję, która może wyświetlać nanosekundy), zrób to na początku/etc/bash.bashrc
(lub gdziekolwiek chcesz rozpocząć śledzenie w dowolnym skrypcie Bash):Dodaj
na końcu
~/.bashrc
(lub na końcu sekcji dowolnego skryptu Bash, którego śledzenie chcesz zatrzymać). Plik\011
Jest ósemkowa znak tabulatora.Powinieneś uzyskać dostęp do śledzenia logowania
/tmp/bashstart.PID.log
który pokazuje znacznik czasu seconds.nanoseconds każdego wykonanego polecenia. Różnica między jednym momentem a drugim to ilość czasu, jaki zajął etap pośredni.W miarę zawężania rzeczy możesz przesuwać się
set -x
później iset +x
wcześniej (lub selektywnie nawiązywać kilka interesujących sekcji).Chociaż nie jest tak drobnoziarnisty jak
date
nanosekundy GNU , Bash 5 zawiera zmienną, która podaje czas w mikrosekundach. Używanie go oszczędza ci tworzenia zewnętrznego pliku wykonywalnego dla każdej linii i działa na komputerach Mac lub w innych miejscach, które nie mają GNUdate
- o ile oczywiście masz Bash 5. Zmień ustawieniePS4
:Jak wskazał @pawamoy, możesz użyć
BASH_XTRACEFD
do wysłania wyniku śledzenia do oddzielnego deskryptora pliku, jeśli masz Bash 4.1 lub nowszy. Z tej odpowiedzi :Spowoduje to, że dane wyjściowe śledzenia trafią do
command.txt
wychodzącego plikustdout
istdout
zostaną wyprowadzone normalnie (lub osobno przekierowane).źródło
exec
powinien przywrócić normalny stan fd2, więc powinieneś otrzymać z powrotem podpowiedź.\D{...}
inPS4
pozwala na rozwinięcie całkowicie dowolnego formatu czasu bez narzutu wydajności związanego z uruchamianiemdate
jako podprocesu.date
rozumie,%N
a Bash 4.2 nie (ponieważstrftime(3)
nie) w systemie GNU - więc arbitralnie z ograniczeniami. Twój punkt widzenia dotyczący wydajności w porównaniu z rozdzielczością jest dobry i użytkownik powinien dokonać mądrego wyboru, pamiętając, że uderzenie w wydajność jest tymczasowo włączone tylko podczas debugowania (i tylko wtedy, gdyset -x
ma miejsce).Profilowy grzmotnąć (4 odpowiedzi)
Edycja: marzec 2016 dodaj
script
metodęCzytając to, a ponieważ profilowanie jest ważnym krokiem, przeprowadziłem kilka testów i badań dotyczących tego całego pytania SO i już opublikowałem odpowiedzi.
Jest odpowiedź 4+:
Ostatniego użycia
script
,scriptreplay
a plik rozrządu .Na koniec małe porównanie występów na koniec.
Używanie
set -x
i,date
ale z ograniczonymi widłamiZapoznaj się z pomysłem @ DennisWilliamson, ale z następującą składnią będzie tylko jedno początkowe rozwidlenie do 3 poleceń:
Robi to
date
tylko raz. Istnieje szybkie demo / test, aby pokazać, jak to działa:Przykładowy skrypt:
Uruchamiając ten skrypt, tworzysz 2 pliki:
/tmp/sample-XXXX.log
i/tmp/sample-XXXX.tim
(gdzie XXXX to identyfikator procesu uruchomionego skryptu).Możesz je zaprezentować za pomocą
paste
:Lub możesz nawet obliczyć czas różnic:
lub na dwóch kolumnach:
Może renderować:
Używanie
trap debug
i/proc/timer_list
na najnowszych jądrach GNU / Linuksa, bez forków .W ostatnich jądrach GNU / Linuksa możesz znaleźć
/proc
plik o nazwietimer_list
:Gdzie aktualny czas jest sumą
5461935212966259 + 1383718821564493249
, ale w nanosekundach.Tak więc do obliczenia upływającego czasu nie ma potrzeby znajomości przesunięcia.
Dla tego rodzaju zadań napisałem elap.bash (V2) , które są pobierane przez następującą składnię:
lub
(Zobacz komentarze dla pełnej składni)
Możesz więc po prostu dodać tę linię u góry swojego skryptu:
Mała próbka:
Renderuj na moim hoście:
Używanie
trap2
zamiasttrap
jako argumentu do polecenia źródła:Wyrenderuje dwie kolumny ostatnie polecenie i sumę :
Za pomocą
strace
Tak,
strace
może wykonać pracę:Ale może być wiele rzeczy!
Korzystanie z bardziej ograniczonego polecenia:
Zrzuci lżejsze kłody:
W zależności od tego, czego szukasz, możesz być bardziej restrykcyjny:
Czytanie ich będzie trochę trudniejsze:
Oryginalny skrypt bash nie jest łatwy do naśladowania w tym ...
Korzystanie
script
,scriptreplay
i rozrządu plikJako część BSD Utils ,
script
(iscriptreplay
) jest bardzo starym narzędziem, które może być używane do profilowania bash, zajmując bardzo mało miejsca.Będzie produkować:
i wygeneruj dwa pliki:
Plik
script.log
zawiera wszystkie ślady iscript.tim
jest plikiem czasu :Możesz zobaczyć całkowity czas wykonania z pierwszą i ostatnią linią pliku dziennika i / lub podsumowując czasy w pliku czasu:
W pliku taktowania drugą wartością jest liczba kolejnych bajtów w odpowiednim pliku dziennika. Pozwala to na ponowne odtwarzanie pliku dziennika opcjonalnie ze współczynnikiem przyspieszenia :
lub
lub
Wyświetlanie czasów i poleceń obok siebie jest również nieco bardziej złożone:
Testy i wnioski
Aby wykonać testy, pobrałem drugą próbkę ze złożonego bash hello world , wykonanie tego skryptu na moim hoście zajmuje około 0,72 sekundy.
Na górze skryptu dodałem jeden z:
według
elap.bash
funkcjiprzez
set -x
iPS4
przez
set -x
i początkowe rozwidlenie do długiego polecenia execprzez
script
(iset +x
)Czasy
I porównaj czasy wykonania (na moim hoście):
Wyjścia
według
elap.bash
funkcjiprzez
set -x
iPS4
przez
set -x
i początkowe rozwidlenie do długiego polecenia exec (i mój drugipaste
przykładowy skrypt)przez
strace
przez
script
Wniosek
Dobrze! Jeśli moje czyste uderzenie jest szybsze niż dotychczasowe rozwidlanie każdego polecenia , moje czyste uderzenie oznacza pewne operacje na każdym poleceniu.
Sposób wyznaczenia niezależnego procesu logowania i przechowywania jest zdecydowanie bardziej wydajny.
strace
to ciekawy sposób, bardziej szczegółowy, ale trudny do odczytania.script
, zscriptreplay
współczynnikiem przyspieszenia też jest bardzo ładny, nie ma takiej samej precyzji, jak ta oparta na wymianie konsoli zamiast wykonywania procesu, ale jest bardzo lekki i wydajny (nie ten sam cel, nie to samo użycie).Na koniec myślę, że bardziej wydajna, pod względem czytelności i wydajności jest
set + 1 fork
pierwsza z tej odpowiedzi, ale w porządku, w zależności od konkretnego przypadku, używam czasamistrace
i / lubscript
też.źródło
exec {BASH_XTRACEFD}>
zamiast tegoexec 3>&2 2>
wypełnić plik dziennika tylko danymi wyjściowymi rejestrowania śledzenia, a nie innymi danymi wyjściowymi standardu standardowego.script.sh
mogę po prostu zrobićbash -c "exec {BASH_XTRACEFD}> >(tee trace.log | sed -u 's/^.*$//' | date -f - +%s.%N > timing.log); set -x; . script.sh
i uzyskać dane profilowania bez modyfikowaniascript.sh
. Kiedy precyzja poniżej sekundy nie jest potrzebna, podoba mi się,bash -c "exec {BASH_XTRACEFD}>trace.log; set -x; PS4='+\t'; . script.sh
który czas oznacza każdą linię śledzenia z drugą dokładnością i bez rozwidlania do tej pory (niskie obciążenie).Często pomaga prześledzić wywołania systemowe
Z instrukcji:
-c Zliczaj czas, wywołania i błędy dla każdego wywołania systemowego i raportuj podsumowanie zakończenia programu.
-f Śledź procesy potomne ...
Nie jest to dokładnie to, czego chcesz i co pokazałby Ci profiler zorientowany liniowo, ale zwykle pomaga znaleźć gorące punkty.
źródło
Możesz rzucić okiem na
trap
polecenie z warunkiem DEBUG . Istnieje sposób ustawienia poleceń, które mają być wykonywane wraz z poleceniami. Zobacz uwagi do odpowiedzi.źródło
help trap
: "Jeśli SIGNAL_SPEC to DEBUG, ARG jest wykonywany przed każdym prostym poleceniem." W Bash 3.2 jest napisane „po”. To jest literówka. Od wersji Bash 2.05b działa wcześniej. Odniesienie : „Ten dokument szczegółowo opisuje zmiany między tą wersją, bash-2.05b-alpha1, a poprzednią wersją, bash-2.05a-release. ... 3. Nowe funkcje w Bash ... w. Pułapka DEBUG jest teraz uruchom przed prostymi poleceniami, ((...)) poleceniami, [[...]] warunkowymi poleceniami i pętlami for ((...)). " Testowanie w każdej wersji potwierdza, że było wcześniej .Time, xtrace, bash -x
set -x
iset+x
( http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_03.html ) pozostają ortodoksyjnym sposobem debugowania skryptu.Bez względu na to, aby poszerzyć nasz horyzont, możliwe jest sprawdzenie jakiegoś systemu debugowania i profilowania dostępnego dla zwykłych programów linuksowych [tutaj jedna z list] , np. Powinien dać użyteczny oparty na valgrind szczególnie do debugowania pamięci lub sysprof do profilu cały system:
Dla sysprof:
A następnie wybierz gałąź podprocesów, które uważasz za interesujące.
Dla Valgrind:
Z jakiegoś bardziej siłowni, wydaje się, że to możliwe, aby widoczny do Valgrind niektóre programy, które zazwyczaj możemy zainstalować z pliku binarnego (np OpenOffice ).
Można przeczytać z często zadawanych pytań valgrind, który
Valgrind
będzie profilował procesy potomne, jeśli zostanie wyraźnie o to poproszony.Zrobi to z włączoną tą opcją
Dodatkowe odniesienia:
źródło
Ten post przez Alan Hargreaves opisuje metody profilowania Bourne skrypt przy użyciu dostawcy DTrace. O ile wiem, działa to z Solarisem i OpenSolarisem (patrz: / bin / sh DTrace Provider ).
Biorąc więc pod uwagę następujący skrypt dtrace (
sh_flowtime.d
w GH na podstawie oryginału ):możesz śledzić przepływ funkcji, w tym czasy delta.
Przykładowe dane wyjściowe:
Następnie za pomocą
sort -nrk7
polecenia możesz posortować dane wyjściowe, aby pokazać najbardziej pochłaniające wywołania.Nie znam żadnych sond dostawców dostępnych dla innych powłok, więc zrób trochę badań (wyszukiwanie na GitHub?) Lub jeśli chcesz zainwestować trochę czasu, możesz napisać takie na podstawie istniejącego przykładu sh : (patrz: Jak aktywować sh Dostawca DTrace? ).
źródło