summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-03-12 22:58:13 +0200
committerPaul Buetow <paul@buetow.org>2025-03-12 22:58:13 +0200
commit0cbf594b5646ec7b020894d918c522be825aacc4 (patch)
treeacebbd79c31a1c1a0efb1400e664c55f52fd4211 /internal
parentac7ebea0920819a14e981da7e3297a8e2e256559 (diff)
refactor
Diffstat (limited to 'internal')
-rw-r--r--internal/eventloop.go46
-rw-r--r--internal/flags/flags.go16
-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)
}