diff options
| author | Paul Buetow <paul@buetow.org> | 2026-02-24 20:16:52 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-02-24 20:16:52 +0200 |
| commit | b8e683e41364fcfd9edda05c4e35a8af3a21835d (patch) | |
| tree | 9124fae6e596143313dac712b4214c262a0b3c82 /internal/flamegraph/trie.go | |
| parent | 85eb1ab91fc388d05530bc48e54da10a9457c201 (diff) | |
flamegraph: add trie aggregation and unit tests
Diffstat (limited to 'internal/flamegraph/trie.go')
| -rw-r--r-- | internal/flamegraph/trie.go | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/internal/flamegraph/trie.go b/internal/flamegraph/trie.go new file mode 100644 index 0000000..dbd3de6 --- /dev/null +++ b/internal/flamegraph/trie.go @@ -0,0 +1,65 @@ +package flamegraph + +import "sort" + +type trieNode struct { + name string + value uint64 + total uint64 + children []*trieNode + childMap map[string]*trieNode +} + +type trie struct { + root *trieNode + maxDepth int +} + +func newTrie() *trie { + return &trie{ + root: &trieNode{ + childMap: make(map[string]*trieNode), + }, + } +} + +func (t *trie) add(frames []string, value uint64) { + node := t.root + for _, frame := range frames { + child, ok := node.childMap[frame] + if !ok { + child = &trieNode{ + name: frame, + childMap: make(map[string]*trieNode), + } + node.children = append(node.children, child) + node.childMap[frame] = child + } + node = child + } + node.value += value +} + +func (t *trie) computeTotals() { + t.maxDepth = 0 + var walk func(node *trieNode, depth int) uint64 + walk = func(node *trieNode, depth int) uint64 { + if depth > t.maxDepth { + t.maxDepth = depth + } + + sort.Slice(node.children, func(i, j int) bool { + return node.children[i].name < node.children[j].name + }) + + total := node.value + for _, child := range node.children { + total += walk(child, depth+1) + } + node.total = total + node.childMap = nil + return total + } + + walk(t.root, 0) +} |
