summaryrefslogtreecommitdiff
path: root/internal/flamegraph/livetrie_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-11 20:02:47 +0300
committerPaul Buetow <paul@buetow.org>2026-05-11 20:02:47 +0300
commit933be1ba2dbb7f6397a4112969bc85a4eac9d155 (patch)
tree1c9f66ee8321880f322b0ddf8030e64dc2af976b /internal/flamegraph/livetrie_test.go
parent662dcfd7ca96d0d4157f9d30b04518db5adfbe45 (diff)
speed up flame graph TUI under heavy event load
Move the per-tick snapshot refresh off the Bubble Tea update goroutine, add a frame ancestry index so navigation and filter helpers run in O(subtree) instead of O(frames), skip refresh and animation while the user is actively pressing keys, and memoize View() output. Keystrokes (pause, filter, navigate) now land within one frame even when the live trie ingests thousands of events per tick. - new SnapshotTree() on LiveTrie bypasses JSON marshal+unmarshal - RefreshFromLiveTrieCmd runs SnapshotTree + layout + ancestry on a background goroutine, coalesced via refreshInFlight, and returns a flameSnapshotReadyMsg the Update loop applies cheaply - driveWindow gate (250 ms after last key press) skips refresh dispatch and snaps frames directly to target without animation while the user is driving - View() caches its rendered string keyed on the inputs that affect output; cache is bypassed during animation Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Diffstat (limited to 'internal/flamegraph/livetrie_test.go')
-rw-r--r--internal/flamegraph/livetrie_test.go12
1 files changed, 6 insertions, 6 deletions
diff --git a/internal/flamegraph/livetrie_test.go b/internal/flamegraph/livetrie_test.go
index 5d4ce47..6a825c0 100644
--- a/internal/flamegraph/livetrie_test.go
+++ b/internal/flamegraph/livetrie_test.go
@@ -371,7 +371,7 @@ func TestLiveTrieConcurrentIngestAndSnapshot(t *testing.T) {
defer wg.Done()
for i := 0; i < 500; i++ {
payload, _ := lt.SnapshotJSON()
- var snap trieSnapshot
+ var snap SnapshotNode
if err := json.Unmarshal(payload, &snap); err != nil {
t.Errorf("unmarshal snapshot: %v", err)
return
@@ -416,7 +416,7 @@ func TestLiveTrieStressHighRateConcurrentSnapshot(t *testing.T) {
return
case <-ticker.C:
payload, _ := lt.SnapshotJSON()
- var snap trieSnapshot
+ var snap SnapshotNode
if err := json.Unmarshal(payload, &snap); err != nil {
errCh <- fmt.Errorf("snapshot json invalid: %w", err)
return
@@ -486,17 +486,17 @@ func newTestPair(comm string, pid uint32, tid uint32, path string, duration uint
return pair
}
-func decodeLiveSnapshot(t *testing.T, lt *LiveTrie) trieSnapshot {
+func decodeLiveSnapshot(t *testing.T, lt *LiveTrie) SnapshotNode {
t.Helper()
payload, _ := lt.SnapshotJSON()
- var snap trieSnapshot
+ var snap SnapshotNode
if err := json.Unmarshal(payload, &snap); err != nil {
t.Fatalf("unmarshal snapshot: %v", err)
}
return snap
}
-func findSnapshotPath(t *testing.T, root *trieSnapshot, names ...string) *trieSnapshot {
+func findSnapshotPath(t *testing.T, root *SnapshotNode, names ...string) *SnapshotNode {
t.Helper()
node := root
for _, name := range names {
@@ -508,7 +508,7 @@ func findSnapshotPath(t *testing.T, root *trieSnapshot, names ...string) *trieSn
return node
}
-func findSnapshotChild(node *trieSnapshot, name string) *trieSnapshot {
+func findSnapshotChild(node *SnapshotNode, name string) *SnapshotNode {
for _, child := range node.Children {
if child.Name == name {
return child