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/flamegraph | |
| parent | ac7ebea0920819a14e981da7e3297a8e2e256559 (diff) | |
refactor
Diffstat (limited to 'internal/flamegraph')
| -rw-r--r-- | internal/flamegraph/flamegraph.go | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/internal/flamegraph/flamegraph.go b/internal/flamegraph/flamegraph.go new file mode 100644 index 0000000..f73bf49 --- /dev/null +++ b/internal/flamegraph/flamegraph.go @@ -0,0 +1,106 @@ +package flamegraph + +import ( + "context" + "fmt" + "ior/internal/event" + "ior/internal/generated/types" + "os" + "path" + "strings" +) + +type counter struct { + count uint64 + duration uint64 +} + +// 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() Flamegraph { + return Flamegraph{ + collapsed: make(map[string]map[types.TraceId]counter), + inCh: make(chan *event.Pair, 4096), + Done: make(chan struct{}), + } +} + +func (f Flamegraph) Start(ctx context.Context) { + go func() { + for { + select { + case ev := <-f.inCh: + pathname := path.Dir(ev.File.Name()) + pathMap, ok := f.collapsed[pathname] + if !ok { + pathMap = make(map[types.TraceId]counter) + } + + traceId := ev.EnterEv.GetTraceId() + cnt := pathMap[traceId] + cnt.count++ + cnt.duration += ev.Duration + pathMap[traceId] = cnt + + f.collapsed[pathname] = pathMap + ev.RecyclePrev() + default: + select { + case <-ctx.Done(): + fmt.Println("Flamegraph processed last event") + f.dump() + close(f.Done) + return + default: + } + } + } + }() +} + +func (f Flamegraph) Add(ev *event.Pair) { + f.inCh <- ev +} + +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 f.collapsed { + var sb strings.Builder + + for i, part := range strings.Split(path, "/") { + if i > 1 { + sb.WriteString(";") + sb.WriteString("/") + } + sb.WriteString(part) + } + + for traceId, cnt := range value { + _, err := fmt.Fprintf(file, "%s;syscall`%s %v\n", sb.String(), traceId, by(cnt)) + if err != nil { + panic(err) + } + } + } +} |
