mirror of
https://github.com/minio/minio.git
synced 2025-01-12 07:23:23 -05:00
profiling: Return goroutines with sleep duration (#12775)
Add a new goroutine file which has another printing format. We need it to see how much time each goroutine was blocked. Easier to detect stops. Co-authored-by: Anis Elleuch <anis@min.io>
This commit is contained in:
parent
9a31030e74
commit
23ef25b57a
38
cmd/utils.go
38
cmd/utils.go
@ -218,25 +218,27 @@ func contains(slice interface{}, elem interface{}) bool {
|
|||||||
// disk since the name of this latter is randomly generated.
|
// disk since the name of this latter is randomly generated.
|
||||||
type profilerWrapper struct {
|
type profilerWrapper struct {
|
||||||
// Profile recorded at start of benchmark.
|
// Profile recorded at start of benchmark.
|
||||||
base []byte
|
records map[string][]byte
|
||||||
stopFn func() ([]byte, error)
|
stopFn func() ([]byte, error)
|
||||||
ext string
|
ext string
|
||||||
}
|
}
|
||||||
|
|
||||||
// recordBase will record the profile and store it as the base.
|
// record will record the profile and store it as the base.
|
||||||
func (p *profilerWrapper) recordBase(name string, debug int) {
|
func (p *profilerWrapper) record(profileType string, debug int, recordName string) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
p.base = nil
|
if p.records == nil {
|
||||||
err := pprof.Lookup(name).WriteTo(&buf, debug)
|
p.records = make(map[string][]byte)
|
||||||
|
}
|
||||||
|
err := pprof.Lookup(profileType).WriteTo(&buf, debug)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.base = buf.Bytes()
|
p.records[recordName] = buf.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base returns the recorded base if any.
|
// Records returns the recorded profiling if any.
|
||||||
func (p profilerWrapper) Base() []byte {
|
func (p profilerWrapper) Records() map[string][]byte {
|
||||||
return p.base
|
return p.records
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop the currently running benchmark.
|
// Stop the currently running benchmark.
|
||||||
@ -268,9 +270,10 @@ func getProfileData() (map[string][]byte, error) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
dst[typ+"."+prof.Extension()] = buf
|
dst[typ+"."+prof.Extension()] = buf
|
||||||
}
|
}
|
||||||
buf = prof.Base()
|
for name, buf := range prof.Records() {
|
||||||
if len(buf) > 0 {
|
if len(buf) > 0 {
|
||||||
dst[typ+"-before"+"."+prof.Extension()] = buf
|
dst[typ+"-"+name+"."+prof.Extension()] = buf
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dst, nil
|
return dst, nil
|
||||||
@ -314,7 +317,7 @@ func startProfiler(profilerType string) (minioProfiler, error) {
|
|||||||
}
|
}
|
||||||
case madmin.ProfilerMEM:
|
case madmin.ProfilerMEM:
|
||||||
runtime.GC()
|
runtime.GC()
|
||||||
prof.recordBase("heap", 0)
|
prof.record("heap", 0, "before")
|
||||||
prof.stopFn = func() ([]byte, error) {
|
prof.stopFn = func() ([]byte, error) {
|
||||||
runtime.GC()
|
runtime.GC()
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
@ -330,7 +333,7 @@ func startProfiler(profilerType string) (minioProfiler, error) {
|
|||||||
return buf.Bytes(), err
|
return buf.Bytes(), err
|
||||||
}
|
}
|
||||||
case madmin.ProfilerMutex:
|
case madmin.ProfilerMutex:
|
||||||
prof.recordBase("mutex", 0)
|
prof.record("mutex", 0, "before")
|
||||||
runtime.SetMutexProfileFraction(1)
|
runtime.SetMutexProfileFraction(1)
|
||||||
prof.stopFn = func() ([]byte, error) {
|
prof.stopFn = func() ([]byte, error) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
@ -339,7 +342,7 @@ func startProfiler(profilerType string) (minioProfiler, error) {
|
|||||||
return buf.Bytes(), err
|
return buf.Bytes(), err
|
||||||
}
|
}
|
||||||
case madmin.ProfilerThreads:
|
case madmin.ProfilerThreads:
|
||||||
prof.recordBase("threadcreate", 0)
|
prof.record("threadcreate", 0, "before")
|
||||||
prof.stopFn = func() ([]byte, error) {
|
prof.stopFn = func() ([]byte, error) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
err := pprof.Lookup("threadcreate").WriteTo(&buf, 0)
|
err := pprof.Lookup("threadcreate").WriteTo(&buf, 0)
|
||||||
@ -347,7 +350,8 @@ func startProfiler(profilerType string) (minioProfiler, error) {
|
|||||||
}
|
}
|
||||||
case madmin.ProfilerGoroutines:
|
case madmin.ProfilerGoroutines:
|
||||||
prof.ext = "txt"
|
prof.ext = "txt"
|
||||||
prof.recordBase("goroutine", 1)
|
prof.record("goroutine", 1, "before")
|
||||||
|
prof.record("goroutine", 2, "before,debug=2")
|
||||||
prof.stopFn = func() ([]byte, error) {
|
prof.stopFn = func() ([]byte, error) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
err := pprof.Lookup("goroutine").WriteTo(&buf, 1)
|
err := pprof.Lookup("goroutine").WriteTo(&buf, 1)
|
||||||
@ -386,8 +390,8 @@ func startProfiler(profilerType string) (minioProfiler, error) {
|
|||||||
|
|
||||||
// minioProfiler - minio profiler interface.
|
// minioProfiler - minio profiler interface.
|
||||||
type minioProfiler interface {
|
type minioProfiler interface {
|
||||||
// Return base profile. 'nil' if none.
|
// Return recorded profiles, each profile associated with a distinct generic name.
|
||||||
Base() []byte
|
Records() map[string][]byte
|
||||||
// Stop the profiler
|
// Stop the profiler
|
||||||
Stop() ([]byte, error)
|
Stop() ([]byte, error)
|
||||||
// Return extension of profile
|
// Return extension of profile
|
||||||
|
Loading…
Reference in New Issue
Block a user