问题
Basically I want to find if my program is leaking goroutines over time. So
I want to see how many goroutines are running over time. Is there any way to do this through pprof
?
I've done go tool pprof http://localhost:8888/debug/pprof/block
.
Which gives me how long is being spent blocked but not how many routines are running.
回答1:
Open http://localhost:8888/debug/pprof/ in your browser. You'll see two relevant links: "goroutine" (http://localhost:8888/debug/pprof/goroutine?debug=1) and "full goroutine stack dump" (http://localhost:8888/debug/pprof/goroutine?debug=2).
The first one will show all goroutines that share the same code as one entry, with the number of such goroutines before their name. For example:
1 @ 0x42f223 0x42f2e4 0x40542f 0x404f4b 0x4a0586 0x4600a1
# 0x4a0586 gitlab.com/gitlab-org/gitlab-ci-multi-runner/commands.(*RunCommand).startWorkers+0x56 /home/me/go/src/gitlab.com/gitlab-org/gitlab-ci-multi-runner/commands/multi.go:164
1 @ 0x42f223 0x43dfd7 0x43d532 0x4a04ed 0x4600a1
# 0x4a04ed gitlab.com/gitlab-org/gitlab-ci-multi-runner/commands.(*RunCommand).processRunners+0x45d /home/me/go/src/gitlab.com/gitlab-org/gitlab-ci-multi-runner/commands/multi.go:147
There's one of both of these goroutines, that's what the 1 before the @ means.
The full dump is extremely useful for finding leaks, it'll show you every goroutine separately, as well as its stack trace and what it's doing (e.g. how long it has been waiting to receive from a channel):
goroutine 49 [chan receive, 2 minutes]:
gitlab.com/gitlab-org/gitlab-ci-multi-runner/commands.(*RunCommand).startWorkers(0xc820103ee0, 0xc820274000, 0xc820274060, 0xc8201d65a0)
/home/me/go/src/gitlab.com/gitlab-org/gitlab-ci-multi-runner/commands/multi.go:164 +0x56
created by gitlab.com/gitlab-org/gitlab-ci-multi-runner/commands.(*RunCommand).Run
/home/me/go/src/gitlab.com/gitlab-org/gitlab-ci-multi-runner/commands/multi.go:294 +0x41b
goroutine 50 [select]:
gitlab.com/gitlab-org/gitlab-ci-multi-runner/commands.(*RunCommand).processRunners(0xc820103ee0, 0x0, 0xc820274060, 0xc8201d65a0)
/home/me/go/src/gitlab.com/gitlab-org/gitlab-ci-multi-runner/commands/multi.go:147 +0x45d
created by gitlab.com/gitlab-org/gitlab-ci-multi-runner/commands.(*RunCommand).startWorkers
/home/me/go/src/gitlab.com/gitlab-org/gitlab-ci-multi-runner/commands/multi.go:165 +0x96
回答2:
As icza pointed out the answer is to use runtime.NumGoroutine()
.
回答3:
As stated above we can definitely use
runtime.NumGoroutine()
to get the current number of goroutines which may either be in running or in waiting state.We can use
Lookup
function to fetch a number of profiles. They can be either pre-defined profiles like goroutine, heap, allocs, mutex, etc. or custom profiles also. More here- We can chain
WriteTo
method defined onProfile
to write to either stdout or to a file. Examplepprof.Lookup("goroutine").WriteTo(writer, 2)
- This will give you significant details about each go-routine like how much time it spent waiting, what was it waiting on, was it sleeping, etc.
- You can use that info to point out where the real issue is.
来源:https://stackoverflow.com/questions/38401778/how-to-profile-number-of-goroutines