funcLookup(name string) *Profile// Lookup returns the profile with the given name,// or nil if no such profile exists.func(p *Profile)WriteTo(w io.Writer, debug int)error// WriteTo writes a pprof-formatted snapshot of the profile to w.// If a write to w returns an error, WriteTo returns that error.// Otherwise, WriteTo returns nil.
Każdy profil ma unikalną nazwę. Kilka profili jest wstępnie zdefiniowanych:
goroutine - stos śladów wszystkich bieżących goroutines
heap - próbkowanie wszystkich alokacji sterty
threadcreate - ślady stosu, które doprowadziły do utworzenia nowego
bloku wątków systemu operacyjnego - ślady stosu, które doprowadziły do zablokowania na elementach pierwotnych synchronizacji
Powinien, woła Stack. „Stos zwraca sformatowany ślad stosu goroutine, który go wywołuje. Dla każdej procedury zawiera informacje o wierszu źródłowym i wartość PC, a następnie próbuje znaleźć dla funkcji Go wywołującą funkcję lub metodę oraz tekst wiersza zawierającego wezwanie."
Intermernet
1
Przepraszamy, wyświetla tylko bieżący ślad stosu goroutine.
4
@HowardGuo Dodałem przykład użycia runtime / pprof do zrzucenia wszystkich śladów stosu.
Intermernet
1
Myślę, że to wyświetla tylko aktualnie uruchomiony goroutine każdego wątku, a nie wszystkie goroutines, np .: play.golang.org/p/0hVB0_LMdm
rogerdpack.
41
Istnieje nakładka HTTP dla runtime/pprofpakietu wymienionego w odpowiedzi Intermernet. Zaimportuj pakiet net / http / pprof , aby zarejestrować procedurę obsługi HTTP dla /debug/pprof:
import _ "net/http/pprof"import _ "net/http"
Uruchom odbiornik HTTP, jeśli jeszcze go nie masz:
Następnie wskaż w przeglądarce http://localhost:6060/debug/pprofmenu lub http://localhost:6060/debug/pprof/goroutine?debug=2pełny zrzut stosu goroutine.
W ten sposób możesz również dowiedzieć się innych ciekawych rzeczy o działającym kodzie. Sprawdź post na blogu, aby zapoznać się z przykładami i szczegółami:
http://blog.golang.org/profiling-go-programs
sprawiłem, że to działa, pokazuje tylko gorutyny wykonane, o ile widzę. Czy jest jakiś sposób, żebym mógł zobaczyć wszystkie „metody”, które są wykonywane po uruchomieniu main.go?
Lukas Lukac
38
Aby naśladować zachowanie Java podczas zrzutu stosu na SIGQUIT, ale nadal pozostawiając uruchomiony program:
Myślę, że tego właśnie szukał autor - naśladuje to, co robi Java, kiedy wysyłasz polecenie kill -QUIT. Jedną małą zmianą, jaką musiałem wprowadzić, była zmiana pierwszej linii pętli for () na: "<- sigs". Innymi słowy, po prostu odrzuć sygnał po odczekaniu na niego. Najnowsze wersje Go nie pozwalają na zadeklarowanie zmiennej bez późniejszego jej użycia.
George Armhold
@Bryan, czy chcesz udzielić licencji na to w ramach BSD lub innych, bardziej liberalnych warunków, oprócz CC-BY-SA 3.0 wymaganej przez StackOverflow?
Podobnie jak w Javie, SIGQUIT może być używany do drukowania śladu stosu programu Go i jego goroutinów.
Kluczową różnicą jest jednak to, że domyślnie wysyłanie SIGQUIT do programów Java nie powoduje ich zakończenia, podczas gdy programy Go kończą działanie.
Takie podejście nie wymaga zmiany kodu, aby wydrukować ślad stosu wszystkich gorutyn istniejących programów.
Zmienna środowiskowa GOTRACEBACK ( zobacz dokumentację pakietu wykonawczego ) kontroluje ilość generowanych danych wyjściowych. Na przykład, aby uwzględnić wszystkie gorutyny, ustaw GOTRACEBACK = all.
Drukowanie śladu stosu jest wyzwalane przez nieoczekiwany warunek wykonawczy (nieobsługiwany sygnał), pierwotnie udokumentowany w tym zatwierdzeniu , udostępniając go co najmniej od wersji Go 1.1.
Alternatywnie, jeśli modyfikacja kodu źródłowego jest opcją, zobacz inne odpowiedzi.
Zwróć uwagę, że w terminalu Linux SIGQUIT można wygodnie wysłać za pomocą kombinacji klawiszy Ctrl+ \.
Przeglądając dokumenty nie znalazłem żadnych wzmianek o SIGQUIT, raczej o SIGABRT. Z moich własnych testów (z go 1.7) ten drugi również działał nad pierwszym.
soltysh
4
to powinna być najlepsza odpowiedź.
Steven Soroka
Dokumentacja odnosi się do „sytuacji, gdy program Go zawiedzie z powodu nieodwracalnej paniki lub nieoczekiwanego stanu środowiska wykonawczego”. Nieprzechwycony sygnał (SIGQUIT itp.) Jest jednym z drugich. Dlaczego wspomniałem o SIGQUIT? Ponieważ OP wyraża swoją miłość do używania SIGQUIT z Javą, a ta odpowiedź podkreśla podobieństwo. Przeformułowanie odpowiedzi, aby była jaśniejsza.
Rodolfo Carvalho
26
Możesz użyć runtime.Stack, aby uzyskać ślad stosu wszystkich goroutines:
Stack formatuje ślad stosu wywołującego gorutynę do bufora i zwraca liczbę bajtów zapisanych w buforze. Jeśli wszystko jest prawdziwe, Stack formatuje ślady wszystkich innych gorutyn w buforze po śladzie dla bieżącej gorutyny.
Czy to format, do którego sprowadza się nieodwracalna panika?
Ztyx
2
Nie zapomnij dodać string (buf) albo wydrukujesz tam surowe bajty.
koda
2
Może robię coś nie tak, a może funkcjonalność się zmieniła, ale to nie pobiera dla mnie niczego oprócz pustego kawałka bajtów?
17xande
1
@koda nie ma potrzeby robić string(buf)tu, fmt.Printf("%s", buf)i fmt.Printf("%s", string(buf))robić dokładnie to samo (patrz Dokumentacja dla fmtpakietu); jedyną różnicą jest to, że stringwersja będzie bufniepotrzebnie kopiować bajty
kbolino
20
Naciśnij CTRL + \
(Jeśli uruchamiasz go w terminalu i chcesz po prostu zabić program i zrzucić procedury go itp.)
Znalazłem to pytanie, szukając sekwencji klawiszy. Chciałem szybko i łatwo sprawdzić, czy mój program przecieka procedury go :)
Najwyraźniej wysłanie SIGQUIT do procesu Java nie kończy go tak , jak zrobi to SIGABRT.
Dave C
Uważam, że jest to najprostsze i najbardziej pasujące rozwiązanie do pierwotnego pytania. Często potrzebujesz śledzenia stosu od razu, bez zmiany kodu.
jotrocken
5
Konieczne jest użycie długości zwróconej przez, runtime.Stack()aby uniknąć drukowania kilku pustych wierszy po śladzie stosu. Następująca funkcja odzyskiwania drukuje ładnie sformatowany ślad:
if r := recover(); r != nil {
log.Printf("Internal error: %v", r))
buf := make([]byte, 1<<16)
stackSize := runtime.Stack(buf, true)
log.Printf("%s\n", string(buf[0:stackSize]))
}
Nigdy tego nie widziałem; na jakiej platformie pracujesz?
Bryan
Czego nie widziałeś? Kod powinien działać na wszystkich platformach; Przetestowałem to na Windows 7, Ubuntu 14.04 i Mac.
David Tootill
Nigdy nie widziałem pustych linii.
Bryan,
4
Domyślnie naciśnij ^\klawisze ( CTRL + \ ), aby zrzucić ślady stosu wszystkich goroutines.
W przeciwnym razie, aby uzyskać bardziej szczegółową kontrolę, możesz użyć panic. Prosty sposób na Go 1.6+ :
gofunc() {
s := make(chan os.Signal, 1)
signal.Notify(s, syscall.SIGQUIT)
<-s
panic("give me the stack")
}()
Następnie uruchom program w ten sposób:
# Press ^\ to dump the stack traces of all the user-created goroutines
$ GOTRACEBACK=all go run main.go
Jeśli chcesz również wydrukować goroutines go runtime:
$ GOTRACEBACK=system go run main.go
Oto wszystkie opcje GOTRACEBACK:
GOTRACEBACK=none całkowicie pomija ślady stosu goroutine.
GOTRACEBACK=single(domyślnie) zachowuje się jak opisano powyżej.
GOTRACEBACK=all dodaje ślady stosu dla wszystkich goroutines utworzonych przez użytkowników.
GOTRACEBACK=system jest jak `ʻall '', ale dodaje ramki stosu dla funkcji wykonawczych i pokazuje gorutynę utworzone wewnętrznie przez środowisko wykonawcze.
GOTRACEBACK=crashjest jak `` system '', ale ulega awarii w sposób specyficzny dla systemu operacyjnego zamiast kończyć działanie. Na przykład w systemach Unix awaria SIGABRTpojawia się, aby wywołać zrzut pamięci.
Zmienna GOTRACEBACK steruje ilością danych wyjściowych generowanych, gdy program Go zawiedzie z powodu nieodwracalnej paniki lub nieoczekiwanego stanu środowiska wykonawczego.
Domyślnie błąd powoduje wydrukowanie śladu stosu dla bieżącego goroutine, eliminując funkcje wewnętrzne systemu wykonawczego, a następnie kończy pracę z kodem zakończenia 2. Niepowodzenie powoduje wydrukowanie śladów stosu dla wszystkich gorutyn, jeśli nie ma aktualnego gorutyny lub wewnętrzne w czasie wykonywania.
Ze względów historycznych ustawienia GOTRACEBACK 0, 1 i 2 są synonimami odpowiednio: none, all i system.
Funkcja SetTraceback pakietu uruchomieniowego / pakietu debugowania umożliwia zwiększenie ilości danych wyjściowych w czasie wykonywania, ale nie może zmniejszyć ilości poniżej wartości określonej przez zmienną środowiskową. Zobacz https://golang.org/pkg/runtime/debug/#SetTraceback .
Odpowiedzi:
Aby wydrukować ślad stosu dla bieżącej gorutyny, użyj
PrintStack()
fromruntime/debug
.Na przykład:
import( "runtime/debug" ) ... debug.PrintStack()
Aby wydrukować ślad stosu dla wszystkich gorutyn, użyj
Lookup
iWriteTo
odruntime/pprof
.func Lookup(name string) *Profile // Lookup returns the profile with the given name, // or nil if no such profile exists. func (p *Profile) WriteTo(w io.Writer, debug int) error // WriteTo writes a pprof-formatted snapshot of the profile to w. // If a write to w returns an error, WriteTo returns that error. // Otherwise, WriteTo returns nil.
Na przykład:
pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
źródło
Stack
. „Stos zwraca sformatowany ślad stosu goroutine, który go wywołuje. Dla każdej procedury zawiera informacje o wierszu źródłowym i wartość PC, a następnie próbuje znaleźć dla funkcji Go wywołującą funkcję lub metodę oraz tekst wiersza zawierającego wezwanie."Istnieje nakładka HTTP dla
runtime/pprof
pakietu wymienionego w odpowiedzi Intermernet. Zaimportuj pakiet net / http / pprof , aby zarejestrować procedurę obsługi HTTP dla/debug/pprof
:import _ "net/http/pprof" import _ "net/http"
Uruchom odbiornik HTTP, jeśli jeszcze go nie masz:
go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }()
Następnie wskaż w przeglądarce
http://localhost:6060/debug/pprof
menu lubhttp://localhost:6060/debug/pprof/goroutine?debug=2
pełny zrzut stosu goroutine.W ten sposób możesz również dowiedzieć się innych ciekawych rzeczy o działającym kodzie. Sprawdź post na blogu, aby zapoznać się z przykładami i szczegółami: http://blog.golang.org/profiling-go-programs
źródło
Aby naśladować zachowanie Java podczas zrzutu stosu na SIGQUIT, ale nadal pozostawiając uruchomiony program:
go func() { sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGQUIT) buf := make([]byte, 1<<20) for { <-sigs stacklen := runtime.Stack(buf, true) log.Printf("=== received SIGQUIT ===\n*** goroutine dump...\n%s\n*** end\n", buf[:stacklen]) } }()
źródło
Podobnie jak w Javie, SIGQUIT może być używany do drukowania śladu stosu programu Go i jego goroutinów.
Kluczową różnicą jest jednak to, że domyślnie wysyłanie SIGQUIT do programów Java nie powoduje ich zakończenia, podczas gdy programy Go kończą działanie.
Takie podejście nie wymaga zmiany kodu, aby wydrukować ślad stosu wszystkich gorutyn istniejących programów.
Zmienna środowiskowa GOTRACEBACK ( zobacz dokumentację pakietu wykonawczego ) kontroluje ilość generowanych danych wyjściowych. Na przykład, aby uwzględnić wszystkie gorutyny, ustaw GOTRACEBACK = all.
Drukowanie śladu stosu jest wyzwalane przez nieoczekiwany warunek wykonawczy (nieobsługiwany sygnał), pierwotnie udokumentowany w tym zatwierdzeniu , udostępniając go co najmniej od wersji Go 1.1.
Alternatywnie, jeśli modyfikacja kodu źródłowego jest opcją, zobacz inne odpowiedzi.
Zwróć uwagę, że w terminalu Linux SIGQUIT można wygodnie wysłać za pomocą kombinacji klawiszy Ctrl+ \.
źródło
Możesz użyć runtime.Stack, aby uzyskać ślad stosu wszystkich goroutines:
buf := make([]byte, 1<<16) runtime.Stack(buf, true) fmt.Printf("%s", buf)
Z dokumentacji:
func Stack(buf []byte, all bool) int
źródło
string(buf)
tu,fmt.Printf("%s", buf)
ifmt.Printf("%s", string(buf))
robić dokładnie to samo (patrz Dokumentacja dlafmt
pakietu); jedyną różnicą jest to, żestring
wersja będziebuf
niepotrzebnie kopiować bajtyNaciśnij CTRL + \
(Jeśli uruchamiasz go w terminalu i chcesz po prostu zabić program i zrzucić procedury go itp.)
Znalazłem to pytanie, szukając sekwencji klawiszy. Chciałem szybko i łatwo sprawdzić, czy mój program przecieka procedury go :)
źródło
W systemach * NIX (w tym OSX) wysyłanie przerwania sygnału
SIGABRT
:pkill -SIGABRT program_name
źródło
Konieczne jest użycie długości zwróconej przez,
runtime.Stack()
aby uniknąć drukowania kilku pustych wierszy po śladzie stosu. Następująca funkcja odzyskiwania drukuje ładnie sformatowany ślad:if r := recover(); r != nil { log.Printf("Internal error: %v", r)) buf := make([]byte, 1<<16) stackSize := runtime.Stack(buf, true) log.Printf("%s\n", string(buf[0:stackSize])) }
źródło
runtime.Trace
;runtime.Stack
wspomniano już półtora roku temu .Domyślnie naciśnij
^\
klawisze ( CTRL + \ ), aby zrzucić ślady stosu wszystkich goroutines.W przeciwnym razie, aby uzyskać bardziej szczegółową kontrolę, możesz użyć
panic
. Prosty sposób na Go 1.6+ :go func() { s := make(chan os.Signal, 1) signal.Notify(s, syscall.SIGQUIT) <-s panic("give me the stack") }()
Następnie uruchom program w ten sposób:
# Press ^\ to dump the stack traces of all the user-created goroutines $ GOTRACEBACK=all go run main.go
Jeśli chcesz również wydrukować goroutines go runtime:
$ GOTRACEBACK=system go run main.go
Oto wszystkie opcje GOTRACEBACK:
GOTRACEBACK=none
całkowicie pomija ślady stosu goroutine.GOTRACEBACK=single
(domyślnie) zachowuje się jak opisano powyżej.GOTRACEBACK=all
dodaje ślady stosu dla wszystkich goroutines utworzonych przez użytkowników.GOTRACEBACK=system
jest jak `ʻall '', ale dodaje ramki stosu dla funkcji wykonawczych i pokazuje gorutynę utworzone wewnętrznie przez środowisko wykonawcze.GOTRACEBACK=crash
jest jak `` system '', ale ulega awarii w sposób specyficzny dla systemu operacyjnego zamiast kończyć działanie. Na przykład w systemach Unix awariaSIGABRT
pojawia się, aby wywołać zrzut pamięci.Oto dokumentacja
źródło