diff options
| author | Paul Buetow <paul@buetow.org> | 2025-03-12 22:58:13 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-03-12 22:58:13 +0200 |
| commit | 0cbf594b5646ec7b020894d918c522be825aacc4 (patch) | |
| tree | acebbd79c31a1c1a0efb1400e664c55f52fd4211 /internal | |
| parent | ac7ebea0920819a14e981da7e3297a8e2e256559 (diff) | |
refactor
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/eventloop.go | 46 | ||||
| -rw-r--r-- | internal/flags/flags.go | 16 | ||||
| -rw-r--r-- | internal/flamegraph/flamegraph.go (renamed from internal/tree/tree.go) | 45 |
3 files changed, 58 insertions, 49 deletions
diff --git a/internal/eventloop.go b/internal/eventloop.go index 9d243d9..26718b5 100644 --- a/internal/eventloop.go +++ b/internal/eventloop.go @@ -12,19 +12,19 @@ import ( "ior/internal/event" "ior/internal/file" "ior/internal/flags" + "ior/internal/flamegraph" . "ior/internal/generated/types" - "ior/internal/tree" ) // TODO: Move in its own package? type eventLoop struct { - flags flags.Flags - filter *eventFilter - enterEvs map[uint32]*event.Pair // Temp. store of sys_enter tracepoints per Tid. - files map[int32]file.File // Track all open files by file descriptor.. - comms map[uint32]string // Program or thread name of the current Tid. - prevPairs map[uint32]*event.Pair // Previous event (to calculate time differences between two events) - tree tree.Tree // Storing all paths in a tree structure for analysis + flags flags.Flags + filter *eventFilter + enterEvs map[uint32]*event.Pair // Temp. store of sys_enter tracepoints per Tid. + files map[int32]file.File // Track all open files by file descriptor.. + comms map[uint32]string // Program or thread name of the current Tid. + prevPairs map[uint32]*event.Pair // Previous event (to calculate time differences between two events) + flamegraph flamegraph.Flamegraph // Storing all paths in a map structure for analysis // Statistics numTracepoints uint @@ -36,13 +36,13 @@ type eventLoop struct { func newEventLoop(flags flags.Flags) *eventLoop { return &eventLoop{ - flags: flags, - filter: newEventFilter(flags), - enterEvs: make(map[uint32]*event.Pair), - files: make(map[int32]file.File), - comms: make(map[uint32]string), - prevPairs: make(map[uint32]*event.Pair), - tree: tree.New(), // TODO: Implement + flags: flags, + filter: newEventFilter(flags), + enterEvs: make(map[uint32]*event.Pair), + files: make(map[int32]file.File), + comms: make(map[uint32]string), + prevPairs: make(map[uint32]*event.Pair), + flamegraph: flamegraph.New(), } } @@ -62,8 +62,8 @@ func (e *eventLoop) stats() string { func (e *eventLoop) run(ctx context.Context, rawCh <-chan []byte) { var recycle bool - if e.flags.TreeEnable { - e.tree.Start(ctx) + if e.flags.FlamegraphEnable { + e.flamegraph.Start(ctx) } if e.flags.PprofEnable { fmt.Println("Profiling, press Ctrl+C to stop") @@ -73,9 +73,9 @@ func (e *eventLoop) run(ctx context.Context, rawCh <-chan []byte) { e.startTime = time.Now() for ev := range e.events(ctx, rawCh) { switch { - case e.flags.TreeEnable: - e.tree.Add(ev) - recycle = false // tree needs to recycle by itself + case e.flags.FlamegraphEnable: + e.flamegraph.Add(ev) + recycle = false // Flamegraph needs to recycle by itself case e.flags.PprofEnable: recycle = true default: @@ -88,9 +88,9 @@ func (e *eventLoop) run(ctx context.Context, rawCh <-chan []byte) { e.numSyscallsAfterFilter++ } - if e.flags.TreeEnable { - fmt.Println("Waiting for tree") - <-e.tree.Done + if e.flags.FlamegraphEnable { + fmt.Println("Waiting for flamegraph") + <-e.flamegraph.Done } } diff --git a/internal/flags/flags.go b/internal/flags/flags.go index 29e4372..236c7ae 100644 --- a/internal/flags/flags.go +++ b/internal/flags/flags.go @@ -8,13 +8,13 @@ import ( ) type Flags struct { - PidFilter int - TidFilter int - EventMapSize int - CommFilter string - PathFilter string - PprofEnable bool - TreeEnable bool + PidFilter int + TidFilter int + EventMapSize int + CommFilter string + PathFilter string + PprofEnable bool + FlamegraphEnable bool } func New() (flags Flags) { @@ -24,7 +24,7 @@ func New() (flags Flags) { flag.StringVar(&flags.CommFilter, "comm", "", "Command to filter for") flag.StringVar(&flags.PathFilter, "path", "", "Path to filter for") flag.BoolVar(&flags.PprofEnable, "pprof", false, "Enable profiling") - flag.BoolVar(&flags.TreeEnable, "tree", false, "Enable tree builder") + flag.BoolVar(&flags.FlamegraphEnable, "flamegraph", false, "Enable flamegraph builder") flag.Parse() return flags diff --git a/internal/tree/tree.go b/internal/flamegraph/flamegraph.go index 9b7ac16..f73bf49 100644 --- a/internal/tree/tree.go +++ b/internal/flamegraph/flamegraph.go @@ -1,4 +1,4 @@ -package tree +package flamegraph import ( "context" @@ -15,29 +15,29 @@ type counter struct { duration uint64 } -// It's a "flat tree" stored in a map, one key per directory -type Tree struct { +// Rename to Flamegraph +type Flamegraph struct { // Collapsed flamegraph stats collector collapsed map[string]map[types.TraceId]counter inCh chan *event.Pair Done chan struct{} } -func New() Tree { - return Tree{ +func New() Flamegraph { + return Flamegraph{ collapsed: make(map[string]map[types.TraceId]counter), inCh: make(chan *event.Pair, 4096), Done: make(chan struct{}), } } -func (t Tree) Start(ctx context.Context) { +func (f Flamegraph) Start(ctx context.Context) { go func() { for { select { - case ev := <-t.inCh: + case ev := <-f.inCh: pathname := path.Dir(ev.File.Name()) - pathMap, ok := t.collapsed[pathname] + pathMap, ok := f.collapsed[pathname] if !ok { pathMap = make(map[types.TraceId]counter) } @@ -48,14 +48,14 @@ func (t Tree) Start(ctx context.Context) { cnt.duration += ev.Duration pathMap[traceId] = cnt - t.collapsed[pathname] = pathMap + f.collapsed[pathname] = pathMap ev.RecyclePrev() default: select { case <-ctx.Done(): - fmt.Println("Tree processed last event") - t.mustDump("ior.collapsed") - close(t.Done) + fmt.Println("Flamegraph processed last event") + f.dump() + close(f.Done) return default: } @@ -64,19 +64,28 @@ func (t Tree) Start(ctx context.Context) { }() } -func (t Tree) Add(ev *event.Pair) { - t.inCh <- ev +func (f Flamegraph) Add(ev *event.Pair) { + f.inCh <- ev } -func (t Tree) mustDump(outfile string) { - fmt.Println("Writing", outfile) +func (f Flamegraph) dump() { + f.dumpBy("ior-by-count-collapsed.flamegraph", func(cnt counter) uint64 { + return cnt.count + }) + f.dumpBy("ior-by-duration-collapsed.flamegraph", func(cnt counter) uint64 { + return cnt.duration + }) +} + +func (f Flamegraph) dumpBy(outfile string, by func(counter) uint64) { + fmt.Println("Dumping", outfile) file, err := os.Create(outfile) if err != nil { panic(err) } defer file.Close() - for path, value := range t.collapsed { + for path, value := range f.collapsed { var sb strings.Builder for i, part := range strings.Split(path, "/") { @@ -88,7 +97,7 @@ func (t Tree) mustDump(outfile string) { } for traceId, cnt := range value { - _, err := fmt.Fprintf(file, "%s;[%s] %v\n", sb.String(), traceId, cnt.count) + _, err := fmt.Fprintf(file, "%s;syscall`%s %v\n", sb.String(), traceId, by(cnt)) if err != nil { panic(err) } |
