detached 0e97e81

Merge branch 'nc/deps-bump': published zero-alloc dependencies

commit
0e97e81717b097c0ea9b642e235a23875eb09844
author
brice · · 2026-10-01 18:59 UTC
merge of
3e34ac2 + 97c224e · diff against the first parent
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
3 files · +12 -27
M go.mod +2 -2
@@ -4,8 +4,8 @@ go 1.27
44
55 require (
66 github.com/bnema/go-wayland-bindings v0.1.0
7- github.com/bnema/purego-xkbcommon v0.1.0
8- github.com/bnema/wlturbo v0.6.0
7+ github.com/bnema/purego-xkbcommon v0.2.0
8+ github.com/bnema/wlturbo v0.6.1
99 github.com/stretchr/testify v1.12.1
1010 golang.org/x/sys v0.48.0
1111 )
@@ -4,8 +4,8 @@ go 1.27
4 4
5 require (5 require (
6 github.com/bnema/go-wayland-bindings v0.1.06 github.com/bnema/go-wayland-bindings v0.1.0
7- github.com/bnema/purego-xkbcommon v0.1.07+ github.com/bnema/purego-xkbcommon v0.2.0
8- github.com/bnema/wlturbo v0.6.08+ github.com/bnema/wlturbo v0.6.1
9 github.com/stretchr/testify v1.12.19 github.com/stretchr/testify v1.12.1
10 golang.org/x/sys v0.48.010 golang.org/x/sys v0.48.0
11 )11 )
M go.sum +4 -4 generated file: collapsed
M seat_wire_test.go +6 -21
@@ -362,27 +362,12 @@ func TestSeatRepeatThroughEpoll(t *testing.T) {
362362 require.Equal(t, n, repeats, "release stops the repeat")
363363 }
364364
365-// xkbAllocsPerPress bounds the allocations of one key press. They all come
366-// from purego-xkbcommon: its functions are registered through purego's
367-// reflection-based RegisterFunc, which allocates the boxed return value (and
368-// more) on every native call, and a press makes four (key_get_one_sym,
369-// compose feed, compose status, key_get_utf8). The library itself adds none;
370-// the zero-allocation guard below proves that. The bound pins the binding's
371-// cost so a regression above it shows.
372-const xkbAllocsPerPress = 20
373-
374-// xkbAllocsPerMask bounds a mask change: update_mask, serialize_mods and
375-// serialize_layout, boxed the same way.
376-const xkbAllocsPerMask = 12
377-
378365 // TestAllocKey measures the steady-state key path over a real socketpair, on
379366 // the real code path (no mocks): key frames in, reader decode, queue, Dispatch
380367 // with xkb state and translation, and the Handler call.
381368 //
382-// Releases make no native call, so a batch of them measures the library's own
383-// cost, which must be zero. Presses add the purego-xkbcommon cost (see
384-// xkbAllocsPerPress); that is measured for ordinary text and for the secret
385-// buffer.
369+// Every path is zero-allocation: releases, text and secret presses, and
370+// modifier masks (purego-xkbcommon v0.2.0 dispatches without allocating).
386371 func TestAllocKey(t *testing.T) {
387372 skipUnderRace(t)
388373 c, srv, peer, s := seatSetup(t)
@@ -431,11 +416,11 @@ func TestAllocKey(t *testing.T) {
431416 }
432417 step := run(batch, 2*pairs)
433418 text := measure("text, 50 presses + releases", step)
434- require.LessOrEqual(t, text, float64(pairs*xkbAllocsPerPress))
419+ require.Zero(t, text, "text presses allocate nothing")
435420 require.Equal(t, "a", h.lastText)
436421
437422 // Modifier masks: an identical mask is a no-op and allocates nothing; a
438- // changing one updates the xkb state (purego-xkbcommon calls, bounded).
423+ // changing one updates the xkb state, also without allocating.
439424 mods := func(depressed uint32) []byte {
440425 b := appendU32(appendU32(nil, 1), depressed)
441426 return frame(kb, 4, appendU32(appendU32(appendU32(b, 0), 0), 0))
@@ -449,12 +434,12 @@ func TestAllocKey(t *testing.T) {
449434 }
450435 require.Zero(t, measure("modifiers, 100 identical masks", run(same, 100)), "identical masks cost nothing")
451436 changes := measure("modifiers, 100 alternating masks", run(changing, 100))
452- require.LessOrEqual(t, changes, float64(100*xkbAllocsPerMask))
437+ require.Zero(t, changes, "mask changes allocate nothing")
453438
454439 buf := neferclient.NewSecretBuffer(4096)
455440 c.Seat().SetSecret(buf)
456441 secret := measure("secret, 50 presses + releases", step)
457- require.LessOrEqual(t, secret, float64(pairs*xkbAllocsPerPress))
442+ require.Zero(t, secret, "secret presses allocate nothing")
458443 require.Empty(t, h.lastText, "no text reaches the handler in secret mode")
459444 require.Positive(t, buf.Len())
460445 buf.Wipe()
@@ -362,27 +362,12 @@ func TestSeatRepeatThroughEpoll(t *testing.T) {
362 require.Equal(t, n, repeats, "release stops the repeat")362 require.Equal(t, n, repeats, "release stops the repeat")
363 }363 }
364 364
365-// xkbAllocsPerPress bounds the allocations of one key press. They all come
366-// from purego-xkbcommon: its functions are registered through purego's
367-// reflection-based RegisterFunc, which allocates the boxed return value (and
368-// more) on every native call, and a press makes four (key_get_one_sym,
369-// compose feed, compose status, key_get_utf8). The library itself adds none;
370-// the zero-allocation guard below proves that. The bound pins the binding's
371-// cost so a regression above it shows.
372-const xkbAllocsPerPress = 20
373-
374-// xkbAllocsPerMask bounds a mask change: update_mask, serialize_mods and
375-// serialize_layout, boxed the same way.
376-const xkbAllocsPerMask = 12
377-
378 // TestAllocKey measures the steady-state key path over a real socketpair, on365 // TestAllocKey measures the steady-state key path over a real socketpair, on
379 // the real code path (no mocks): key frames in, reader decode, queue, Dispatch366 // the real code path (no mocks): key frames in, reader decode, queue, Dispatch
380 // with xkb state and translation, and the Handler call.367 // with xkb state and translation, and the Handler call.
381 //368 //
382-// Releases make no native call, so a batch of them measures the library's own369+// Every path is zero-allocation: releases, text and secret presses, and
383-// cost, which must be zero. Presses add the purego-xkbcommon cost (see370+// modifier masks (purego-xkbcommon v0.2.0 dispatches without allocating).
384-// xkbAllocsPerPress); that is measured for ordinary text and for the secret
385-// buffer.
386 func TestAllocKey(t *testing.T) {371 func TestAllocKey(t *testing.T) {
387 skipUnderRace(t)372 skipUnderRace(t)
388 c, srv, peer, s := seatSetup(t)373 c, srv, peer, s := seatSetup(t)
@@ -431,11 +416,11 @@ func TestAllocKey(t *testing.T) {
431 }416 }
432 step := run(batch, 2*pairs)417 step := run(batch, 2*pairs)
433 text := measure("text, 50 presses + releases", step)418 text := measure("text, 50 presses + releases", step)
434- require.LessOrEqual(t, text, float64(pairs*xkbAllocsPerPress))419+ require.Zero(t, text, "text presses allocate nothing")
435 require.Equal(t, "a", h.lastText)420 require.Equal(t, "a", h.lastText)
436 421
437 // Modifier masks: an identical mask is a no-op and allocates nothing; a422 // Modifier masks: an identical mask is a no-op and allocates nothing; a
438- // changing one updates the xkb state (purego-xkbcommon calls, bounded).423+ // changing one updates the xkb state, also without allocating.
439 mods := func(depressed uint32) []byte {424 mods := func(depressed uint32) []byte {
440 b := appendU32(appendU32(nil, 1), depressed)425 b := appendU32(appendU32(nil, 1), depressed)
441 return frame(kb, 4, appendU32(appendU32(appendU32(b, 0), 0), 0))426 return frame(kb, 4, appendU32(appendU32(appendU32(b, 0), 0), 0))
@@ -449,12 +434,12 @@ func TestAllocKey(t *testing.T) {
449 }434 }
450 require.Zero(t, measure("modifiers, 100 identical masks", run(same, 100)), "identical masks cost nothing")435 require.Zero(t, measure("modifiers, 100 identical masks", run(same, 100)), "identical masks cost nothing")
451 changes := measure("modifiers, 100 alternating masks", run(changing, 100))436 changes := measure("modifiers, 100 alternating masks", run(changing, 100))
452- require.LessOrEqual(t, changes, float64(100*xkbAllocsPerMask))437+ require.Zero(t, changes, "mask changes allocate nothing")
453 438
454 buf := neferclient.NewSecretBuffer(4096)439 buf := neferclient.NewSecretBuffer(4096)
455 c.Seat().SetSecret(buf)440 c.Seat().SetSecret(buf)
456 secret := measure("secret, 50 presses + releases", step)441 secret := measure("secret, 50 presses + releases", step)
457- require.LessOrEqual(t, secret, float64(pairs*xkbAllocsPerPress))442+ require.Zero(t, secret, "secret presses allocate nothing")
458 require.Empty(t, h.lastText, "no text reaches the handler in secret mode")443 require.Empty(t, h.lastText, "no text reaches the handler in secret mode")
459 require.Positive(t, buf.Len())444 require.Positive(t, buf.Len())
460 buf.Wipe()445 buf.Wipe()

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 1

Tags 4

↑↓ moveenter openesc close