mirror of
https://github.com/ipfs/kubo.git
synced 2025-05-17 15:06:47 +08:00

* feat: add block profiling to collect-profiles.sh * feat: add more profiles to 'ipfs diag profile' This adds mutex and block profiles, and brings the command up-to-par with 'collect-profiles.sh', so that we can remove it. Profiles are also now collected concurrently, which improves the runtime from (profile_time * num_profiles) to just (profile_time). Note that this has a backwards-incompatible change, removing --cpu-profile-time in favor of the more general --profile-time, which covers all sampling profiles. * docs(cli): ipfs diag profile * add CLI flag to select specific diag collectors Co-authored-by: Marcin Rataj <lidel@lidel.org>
173 lines
3.4 KiB
Go
173 lines
3.4 KiB
Go
package profile
|
|
|
|
import (
|
|
"archive/zip"
|
|
"bytes"
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestProfiler(t *testing.T) {
|
|
allCollectors := []string{
|
|
CollectorGoroutinesStack,
|
|
CollectorGoroutinesPprof,
|
|
CollectorVersion,
|
|
CollectorHeap,
|
|
CollectorBin,
|
|
CollectorCPU,
|
|
CollectorMutex,
|
|
CollectorBlock,
|
|
}
|
|
|
|
cases := []struct {
|
|
name string
|
|
opts Options
|
|
goos string
|
|
|
|
expectFiles []string
|
|
}{
|
|
{
|
|
name: "happy case",
|
|
opts: Options{
|
|
Collectors: allCollectors,
|
|
ProfileDuration: 1 * time.Millisecond,
|
|
MutexProfileFraction: 4,
|
|
BlockProfileRate: 50 * time.Nanosecond,
|
|
},
|
|
expectFiles: []string{
|
|
"goroutines.stacks",
|
|
"goroutines.pprof",
|
|
"version.json",
|
|
"heap.pprof",
|
|
"ipfs",
|
|
"cpu.pprof",
|
|
"mutex.pprof",
|
|
"block.pprof",
|
|
},
|
|
},
|
|
{
|
|
name: "windows",
|
|
opts: Options{
|
|
Collectors: allCollectors,
|
|
ProfileDuration: 1 * time.Millisecond,
|
|
MutexProfileFraction: 4,
|
|
BlockProfileRate: 50 * time.Nanosecond,
|
|
},
|
|
goos: "windows",
|
|
expectFiles: []string{
|
|
"goroutines.stacks",
|
|
"goroutines.pprof",
|
|
"version.json",
|
|
"heap.pprof",
|
|
"ipfs.exe",
|
|
"cpu.pprof",
|
|
"mutex.pprof",
|
|
"block.pprof",
|
|
},
|
|
},
|
|
{
|
|
name: "sampling profiling disabled",
|
|
opts: Options{
|
|
Collectors: allCollectors,
|
|
MutexProfileFraction: 4,
|
|
BlockProfileRate: 50 * time.Nanosecond,
|
|
},
|
|
expectFiles: []string{
|
|
"goroutines.stacks",
|
|
"goroutines.pprof",
|
|
"version.json",
|
|
"heap.pprof",
|
|
"ipfs",
|
|
},
|
|
},
|
|
{
|
|
name: "Mutex profiling disabled",
|
|
opts: Options{
|
|
Collectors: allCollectors,
|
|
ProfileDuration: 1 * time.Millisecond,
|
|
BlockProfileRate: 50 * time.Nanosecond,
|
|
},
|
|
expectFiles: []string{
|
|
"goroutines.stacks",
|
|
"goroutines.pprof",
|
|
"version.json",
|
|
"heap.pprof",
|
|
"ipfs",
|
|
"cpu.pprof",
|
|
"block.pprof",
|
|
},
|
|
},
|
|
{
|
|
name: "block profiling disabled",
|
|
opts: Options{
|
|
Collectors: allCollectors,
|
|
ProfileDuration: 1 * time.Millisecond,
|
|
MutexProfileFraction: 4,
|
|
BlockProfileRate: 0,
|
|
},
|
|
expectFiles: []string{
|
|
"goroutines.stacks",
|
|
"goroutines.pprof",
|
|
"version.json",
|
|
"heap.pprof",
|
|
"ipfs",
|
|
"cpu.pprof",
|
|
"mutex.pprof",
|
|
},
|
|
},
|
|
{
|
|
name: "single collector",
|
|
opts: Options{
|
|
Collectors: []string{CollectorVersion},
|
|
ProfileDuration: 1 * time.Millisecond,
|
|
MutexProfileFraction: 4,
|
|
BlockProfileRate: 0,
|
|
},
|
|
expectFiles: []string{
|
|
"version.json",
|
|
},
|
|
},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
if c.goos != "" {
|
|
oldGOOS := goos
|
|
goos = c.goos
|
|
defer func() { goos = oldGOOS }()
|
|
}
|
|
|
|
buf := &bytes.Buffer{}
|
|
archive := zip.NewWriter(buf)
|
|
err := WriteProfiles(context.Background(), archive, c.opts)
|
|
require.NoError(t, err)
|
|
|
|
err = archive.Close()
|
|
require.NoError(t, err)
|
|
|
|
zr, err := zip.NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
|
|
require.NoError(t, err)
|
|
|
|
for _, f := range zr.File {
|
|
logger.Info("zip file: ", f.Name)
|
|
}
|
|
|
|
require.Equal(t, len(c.expectFiles), len(zr.File))
|
|
|
|
for _, expectedFile := range c.expectFiles {
|
|
func() {
|
|
f, err := zr.Open(expectedFile)
|
|
require.NoError(t, err)
|
|
defer f.Close()
|
|
fi, err := f.Stat()
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, fi.Size())
|
|
}()
|
|
}
|
|
})
|
|
}
|
|
}
|