feat/hints a471fa4

commit_hotpath_bench_test.go RawHistoryFolder

1package wayland
2
3import (
4	"context"
5	"path/filepath"
6	"testing"
7	"time"
8
9	"github.com/bnema/go-wayland-bindings/server/fifo"
10	"github.com/bnema/go-wayland-bindings/server/viewporter"
11	"github.com/bnema/go-wayland-bindings/server/wayland"
12	"github.com/bnema/neferwl/internal/adapters/logging"
13	"github.com/bnema/wlturbo"
14	"golang.org/x/sys/unix"
15)
16
17// BenchmarkProtocolQueuedCommit measures a real client's requests and server
18// dispatch, queue capture, and paced application. Socket roundtrips synchronize
19// each frame; this is end-to-end latency, not an allocation-free apply microbench.
20func BenchmarkProtocolQueuedCommit(b *testing.B) {
21	dir := b.TempDir()
22	s, err := New(Options{RuntimeDir: dir, Outputs: testOutputs}, Channels{}, logging.For(context.Background(), "wayland"))
23	if err != nil {
24		b.Fatal(err)
25	}
26	ctx, cancel := context.WithCancel(context.Background())
27	done := make(chan error, 1)
28	go func() { done <- s.Run(ctx) }()
29	defer func() { cancel(); <-done }()
30	c, err := wlturbo.Connect(filepath.Join(dir, s.SocketName()))
31	if err != nil {
32		b.Fatal(err)
33	}
34	defer func() {
35		_ = c.Close()
36		forgetWireClient(c)
37	}()
38	if err := c.Roundtrip(); err != nil {
39		b.Fatal(err)
40	}
41	bind := func(name string) uint32 {
42		g, ok := c.Registry().FindGlobal(name)
43		if !ok {
44			b.Fatalf("missing %s", name)
45		}
46		id, err := bindWireID(c, g.Name, g.Interface, 1)
47		if err != nil {
48			b.Fatal(err)
49		}
50		return id
51	}
52	send := func(id, op uint32, args ...any) {
53		if err := wireRequest(c, id, uint16(op), nil, args...); err != nil {
54			b.Fatal(err)
55		}
56	}
57	comp, fm, vpm := bind("wl_compositor"), bind("wp_fifo_manager_v1"), bind("wp_viewporter")
58	shm := bind("wl_shm")
59	register := func(id uint32) {
60		p := &protocolProxy{}
61		p.SetID(id)
62		registerWireProxy(c, p)
63	}
64	register(shm)
65	surf := c.AllocateID()
66	send(comp, wayland.CompositorRequestCreateSurface, surf)
67	register(surf)
68	f := c.AllocateID()
69	send(fm, fifo.WpFifoManagerV1RequestGetFifo, f, surf)
70	register(f)
71	vp := c.AllocateID()
72	send(vpm, viewporter.WpViewporterRequestGetViewport, vp, surf)
73	register(vp)
74	// One real SHM buffer, reused for every commit.
75	fd, err := unix.MemfdCreate("bench-buffer", 0)
76	if err != nil {
77		b.Fatal(err)
78	}
79	defer unix.Close(fd)
80	if err := unix.Ftruncate(fd, 4); err != nil {
81		b.Fatal(err)
82	}
83	pool, buf := c.AllocateID(), c.AllocateID()
84	register(pool)
85	register(buf)
86	if err := wireRequest(c, shm, uint16(wayland.ShmRequestCreatePool), []int{fd}, pool, int32(4)); err != nil {
87		b.Fatal(err)
88	}
89	send(pool, wayland.ShmPoolRequestCreateBuffer, buf, int32(0), int32(1), int32(1), int32(4), uint32(0))
90	if err := c.Roundtrip(); err != nil {
91		b.Fatal(err)
92	}
93	// Install a barrier so each measured commit really waits in the queue.
94	send(f, fifo.WpFifoV1RequestSetBarrier)
95	send(surf, wayland.SurfaceRequestCommit)
96	if err := c.Roundtrip(); err != nil {
97		b.Fatal(err)
98	}
99	b.ReportAllocs()
100	b.ResetTimer()
101	for range b.N {
102		send(f, fifo.WpFifoV1RequestWaitBarrier)
103		send(surf, wayland.SurfaceRequestAttach, buf, int32(0), int32(0))
104		send(surf, wayland.SurfaceRequestDamage, int32(0), int32(0), int32(1), int32(1))
105		send(vp, viewporter.WpViewportRequestSetDestination, int32(1), int32(1))
106		send(surf, wayland.SurfaceRequestCommit)
107		// Later requests must not be consumed by the captured update.
108		send(vp, viewporter.WpViewportRequestSetDestination, int32(2), int32(2))
109		if err := c.Roundtrip(); err != nil {
110			b.Fatal(err)
111		}
112		s.display.Do(func() {
113			for _, state := range s.surfaces {
114				if state.wl != nil && state.wl.ID() == surf {
115					if len(state.queue) != 1 {
116						b.Errorf("queued commits: %d", len(state.queue))
117						return
118					}
119					state.barrier = false
120					s.tickFifo(time.Now(), nil)
121					if len(state.queue) != 0 {
122						b.Error("commit still queued")
123					}
124					return
125				}
126			}
127			b.Error("missing surface")
128		})
129		// Next iteration overwrites the pending viewport destination.
130		send(f, fifo.WpFifoV1RequestSetBarrier)
131		send(surf, wayland.SurfaceRequestCommit)
132		if err := c.Roundtrip(); err != nil {
133			b.Fatal(err)
134		}
135	}
136}

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 23

Tags 10

↑↓ moveenter openesc close