diff options
| author | Paul Buetow <paul@buetow.org> | 2025-03-14 23:41:54 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-03-14 23:41:54 +0200 |
| commit | 5cac6a84181a6121e27c5c763a3e34254180fa4b (patch) | |
| tree | 83bf76348990052452d38d3feacc20f757b27695 /internal | |
| parent | 3edde70ef17d23a3f2fcb0fac11a50e8810ab943 (diff) | |
parallel rite collapsed flamegraphs
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/eventloop.go | 12 | ||||
| -rw-r--r-- | internal/file/file.go | 18 | ||||
| -rw-r--r-- | internal/flamegraph/flamegraph.go | 21 |
3 files changed, 32 insertions, 19 deletions
diff --git a/internal/eventloop.go b/internal/eventloop.go index 1e7fea6..11a184d 100644 --- a/internal/eventloop.go +++ b/internal/eventloop.go @@ -3,7 +3,6 @@ package internal import "C" import ( - "bytes" "context" "fmt" "os" @@ -181,9 +180,7 @@ func (e *eventLoop) syscallExit(exitEv event.Event, ch chan<- *event.Pair) { fd := int32(ev.ExitEv.(*RetEvent).Ret) // It's from an array, so only create string from array until first 0 byte // TODO: This could speed up the path filter as well - // TODO: Hopefully, this won't cause a panic when the filename is as long as the array itself - filePath := string(openEv.Filename[:bytes.IndexByte(openEv.Filename[:], 0)]) - file := file.NewFd(fd, filePath) + file := file.NewFd(fd, openEv.Filename[:]) if fd >= 0 { e.files[fd] = file } @@ -192,15 +189,12 @@ func (e *eventLoop) syscallExit(exitEv event.Event, ch chan<- *event.Pair) { case *NameEvent: nameEvent := ev.EnterEv.(*NameEvent) - ev.File = file.OldnameNewnameFile{ - Oldname: string(nameEvent.Oldname[:]), - Newname: string(nameEvent.Newname[:]), - } + ev.File = file.NewOldnameNewname(nameEvent.Oldname[:], nameEvent.Newname[:]) ev.Comm = e.comm(ev.EnterEv.GetTid()) case *PathEvent: nameEvent := ev.EnterEv.(*PathEvent) - ev.File = file.PathnameFile{Pathname: string(nameEvent.Pathname[:])} + ev.File = file.NewPathname(nameEvent.Pathname[:]) ev.Comm = e.comm(ev.EnterEv.GetTid()) case *FdEvent: diff --git a/internal/file/file.go b/internal/file/file.go index 4d9afab..a9de8d3 100644 --- a/internal/file/file.go +++ b/internal/file/file.go @@ -1,6 +1,7 @@ package file import ( + "bytes" "fmt" "os" "strconv" @@ -17,8 +18,8 @@ type FdFile struct { name string } -func NewFd(fd int32, name string) FdFile { - return FdFile{fd, name} +func NewFd(fd int32, name []byte) FdFile { + return FdFile{fd, stringValue(name)} } func NewFdWithPid(fd int32, pid uint32) FdFile { @@ -51,6 +52,10 @@ type OldnameNewnameFile struct { Oldname, Newname string } +func NewOldnameNewname(oldname, newname []byte) OldnameNewnameFile { + return OldnameNewnameFile{stringValue(oldname), stringValue(newname)} +} + func (f OldnameNewnameFile) Name() string { return f.Newname } @@ -70,6 +75,10 @@ type PathnameFile struct { Pathname string } +func NewPathname(pathname []byte) PathnameFile { + return PathnameFile{stringValue(pathname)} +} + func (f PathnameFile) Name() string { return f.Pathname } @@ -82,3 +91,8 @@ func (f PathnameFile) String() string { return sb.String() } + +func stringValue(byteStr []byte) string { + // TODO: Hopefully, this won't cause a panic when the filename is as long as the array itself + return string(byteStr[:bytes.IndexByte(byteStr, 0)]) +} diff --git a/internal/flamegraph/flamegraph.go b/internal/flamegraph/flamegraph.go index 9e15889..6c5df63 100644 --- a/internal/flamegraph/flamegraph.go +++ b/internal/flamegraph/flamegraph.go @@ -7,6 +7,7 @@ import ( "ior/internal/generated/types" "os" "strings" + "sync" "time" ) @@ -18,8 +19,6 @@ type counter struct { // TODO: Profile for CPU usage. If too slow, can fan out into multiple maps and // then merge at the end the maps. type Flamegraph struct { - // TODO: Keep al lthe individual files at the leaf in a map as well. - // And when dumped, only dump the N "highest" and summarize the other ones. collapsed map[string]map[types.TraceId]counter inCh chan *event.Pair Done chan struct{} @@ -74,21 +73,28 @@ func (f Flamegraph) Add(ev *event.Pair) { } func (f Flamegraph) dump() { - f.dumpBy("ior-by-path-count-flamegraph.collapsed", true, func(cnt counter) uint64 { + var wg sync.WaitGroup + wg.Add(4) + + go f.dumpBy(&wg, "ior-by-path-count-flamegraph.collapsed", true, func(cnt counter) uint64 { return cnt.count }) - f.dumpBy("ior-by-path-duration-flamegraph.collapsed", true, func(cnt counter) uint64 { + go f.dumpBy(&wg, "ior-by-path-duration-flamegraph.collapsed", true, func(cnt counter) uint64 { return cnt.duration }) - f.dumpBy("ior-by-syscall-count-flamegraph.collapsed", false, func(cnt counter) uint64 { + go f.dumpBy(&wg, "ior-by-syscall-count-flamegraph.collapsed", false, func(cnt counter) uint64 { return cnt.count }) - f.dumpBy("ior-by-syscall-duration-flamegraph.collapsed", false, func(cnt counter) uint64 { + go f.dumpBy(&wg, "ior-by-syscall-duration-flamegraph.collapsed", false, func(cnt counter) uint64 { return cnt.duration }) + + wg.Wait() } -func (f Flamegraph) dumpBy(outfile string, syscallAtTop bool, by func(counter) uint64) { +func (f Flamegraph) dumpBy(wg *sync.WaitGroup, outfile string, syscallAtTop bool, by func(counter) uint64) { + defer wg.Done() + fmt.Println("Dumping", outfile) file, err := os.Create(outfile) if err != nil { @@ -105,7 +111,6 @@ func (f Flamegraph) dumpBy(outfile string, syscallAtTop bool, by func(counter) u sb.WriteString("/") } sb.WriteString(part) - fmt.Println("DEBUG part", i, part, len(part)) } for traceId, cnt := range value { |
