surface_perf_test.go RawHistoryFolder

1package wayland
2
3import (
4	"context"
5	"fmt"
6	"testing"
7
8	"github.com/bnema/neferwl/internal/logging"
9	"github.com/bnema/neferwl/internal/ports"
10)
11
12// TestEffectiveInputEmptyTreeAllocations guards against a heap-allocated
13// recursive closure for every input-region traversal of a tiled tree.
14func TestEffectiveInputEmptyTreeAllocations(t *testing.T) {
15	root := &surface{}
16	for range 64 {
17		child := &surface{}
18		root.sub.children = append(root.sub.children, child)
19		root.sub.layout = append(root.sub.layout, childLayout{child: child})
20	}
21	walk := func() {
22		all, rects := root.effectiveInput()
23		if all || len(rects) != 0 {
24			t.Fatal("empty tree has input")
25		}
26	}
27	if allocs := testing.AllocsPerRun(100, walk); allocs != 0 {
28		t.Errorf("empty tiled input traversal: %.1f allocs, want 0", allocs)
29	}
30}
31
32// TestTiledCommitPublishAllocations exercises real content publication without
33// a client connection, holding old snapshots while subsequent commits publish.
34func TestTiledCommitPublishAllocations(t *testing.T) {
35	// The top-level test is listed in Makefile perf-check; this subtest guards
36	// the per-commit update storage after its first retirement.
37	t.Run("queueUpdateSteadyState", func(t *testing.T) {
38		srv := &Server{fifoSurfaces: make(map[*surface]struct{}), frameReady: make(chan struct{}, 1)}
39		surf := &surface{server: srv}
40		commit := func() {
41			surf.queueUpdate()
42			surf.dropQueue()
43		}
44		commit()
45		if allocs := testing.AllocsPerRun(100, commit); allocs != 0 {
46			t.Errorf("steady-state queueUpdate/dropQueue: %.1f allocs/commit; want 0", allocs)
47		}
48	})
49	for _, count := range []int{16, 64} {
50		t.Run(fmt.Sprintf("%d", count), func(t *testing.T) {
51			channels := Channels{Contents: make(chan ports.SurfaceContent, 1)}
52			srv, err := New(Options{RuntimeDir: t.TempDir(), Outputs: testOutputs}, channels, logging.For(context.Background(), "wayland"))
53			if err != nil {
54				t.Fatal(err)
55			}
56			root := &surface{server: srv, content: ports.SurfaceContent{Width: 1, Height: 1}, has: true, identity: 1}
57			root.xdg = &xdgSurface{window: &window{id: 1, mapped: true}}
58			for i := range count {
59				child := &surface{server: srv, has: true, content: ports.SurfaceContent{Width: 1, Height: 1}, identity: uint64(i + 2)}
60				child.sub.parent = root
61				root.sub.children = append(root.sub.children, child)
62				root.sub.layout = append(root.sub.layout, childLayout{child: child, x: i})
63			}
64			publish := func() { root.redraw() }
65			root.treeDirty = true
66			publish()
67			first := srv.contents[1]
68			publish()
69			if first.Seq != 1 || len(first.Children) != count || len(first.DamageHistory) != 1 {
70				t.Fatalf("previous publication changed: %+v", first)
71			}
72			if allocs := testing.AllocsPerRun(100, publish); allocs > 2 {
73				t.Errorf("%d children: %.1f allocs/publication; want <=2", count, allocs)
74			} else {
75				t.Logf("%d children: %.1f allocs/unchanged publication", count, allocs)
76			}
77			// A queued commit with an unchanged layout must not allocate
78			// proportionally to the number of children.
79			root.sub.pendingLayout = root.sub.layout
80			queue := func() { _ = root.takePending() }
81			if allocs := testing.AllocsPerRun(100, queue); allocs > 0 {
82				t.Errorf("%d children: %.1f allocs/queued commit; want 0", count, allocs)
83			} else {
84				t.Logf("%d children: %.1f allocs/takePending", count, allocs)
85			}
86			commit := func() {
87				root.queueUpdate()
88				root.dropQueue()
89			}
90			if allocs := testing.AllocsPerRun(100, commit); allocs != 0 {
91				t.Errorf("%d children: %.1f allocs/queueUpdate; want 0", count, allocs)
92			} else {
93				t.Logf("%d children: %.1f allocs/queueUpdate", count, allocs)
94			}
95			if first.Seq != 1 || len(first.Children) != count || len(first.DamageHistory) != 1 || first.DamageHistory[0].Seq != 1 {
96				t.Fatal("previous publication was mutated")
97			}
98			// An applied child change rebuilds into a distinct immutable slice.
99			root.sub.children[count-1].version++
100			root.treeDirty = true
101			publish()
102			if first.Children[count-1].Version != 0 || srv.contents[1].Children[count-1].Version != 1 {
103				t.Fatal("child version leaked into an earlier publication")
104			}
105			if &first.Children[0] == &srv.contents[1].Children[0] {
106				t.Fatal("rebuild reused previously published children storage")
107			}
108			// Rebuilding a changed child's immutable snapshot must have a
109			// constant allocation count, regardless of tree size.
110			child := root.sub.children[count-1]
111			changed := func() {
112				child.version++
113				root.treeDirty = true
114				root.redraw()
115			}
116			if allocs := testing.AllocsPerRun(100, changed); allocs > 3 {
117				t.Errorf("%d children: %.1f allocs/changed publication; want <=3", count, allocs)
118			} else {
119				t.Logf("%d children: %.1f allocs/changed publication", count, allocs)
120			}
121		})
122	}
123}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 25

Tags 10

↑↓ moveenter openesc close