build(deps): use purego-xkbcommon v0.2.0 and wlturbo v0.6.1, require zero-alloc key path
- commit
- 97c224eee4052d61038c3ab8fab8ad8f5cddf3ee
- author
- brice · · 2026-10-01 18:59 UTC
- parent
- 3e34ac2
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
3 files · +12 -27
M go.mod +2 -2
| @@ -4,8 +4,8 @@ go 1.27 | |||
| 4 | 4 | ||
| 5 | 5 | require ( | |
| 6 | 6 | 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 | |
| 9 | 9 | github.com/stretchr/testify v1.12.1 | |
| 10 | 10 | golang.org/x/sys v0.48.0 | |
| 11 | 11 | ) | |
| @@ -4,8 +4,8 @@ go 1.27 | |||||
| 4 | 4 | ||||
| 5 | require ( | 5 | require ( | ||
| 6 | github.com/bnema/go-wayland-bindings v0.1.0 | 6 | github.com/bnema/go-wayland-bindings v0.1.0 | ||
| 7 | - | github.com/bnema/purego-xkbcommon v0.1.0 | 7 | + | github.com/bnema/purego-xkbcommon v0.2.0 |
| 8 | - | github.com/bnema/wlturbo v0.6.0 | 8 | + | github.com/bnema/wlturbo v0.6.1 |
| 9 | github.com/stretchr/testify v1.12.1 | 9 | github.com/stretchr/testify v1.12.1 | ||
| 10 | golang.org/x/sys v0.48.0 | 10 | golang.org/x/sys v0.48.0 | ||
| 11 | ) | 11 | ) | ||
M go.sum +4 -4
| @@ -2,10 +2,10 @@ github.com/bnema/go-wayland-bindings v0.1.0 h1:mi2vNa8BB5ZCo/hq/9d6Af01yhqY6QXAZ | |||
| 2 | 2 | github.com/bnema/go-wayland-bindings v0.1.0/go.mod h1:eWOgjp9vzZEqxm059q1G9F5NXplmv9UAmrDJiivxVjA= | |
| 3 | 3 | github.com/bnema/purego v0.13.0-bnema.1 h1:fKRdztnvTmRqAjANMoN+utEIH73dvPqVPJh2iZCCAO8= | |
| 4 | 4 | github.com/bnema/purego v0.13.0-bnema.1/go.mod h1:xS1iX3noypxnbOUEUAqOvkfnUzgHuu19VtL4+dfUMJM= | |
| 5 | - | github.com/bnema/purego-xkbcommon v0.1.0 h1:VHNf9shPpafKxdTERcwCNJKHhSd4IG2tjmLsDACKnuw= | |
| 6 | - | github.com/bnema/purego-xkbcommon v0.1.0/go.mod h1:GE8JGmR/rqdklz96tFaFU7M5kI7jN1ma5mh+rz+XXrg= | |
| 7 | - | github.com/bnema/wlturbo v0.6.0 h1:sEEf22j+PIrSV9NTlognbSJ1/CUoeQj/lwpUkE6D1nY= | |
| 8 | - | github.com/bnema/wlturbo v0.6.0/go.mod h1:4i1k1wyw7FDWOkh2hg1ZwPfrPRn3+E6WrYg9Qrt74CA= | |
| 5 | + | github.com/bnema/purego-xkbcommon v0.2.0 h1:UWh5rSJIBhYImg8wZ98UzK4QNt7gvkKR6gFseO21mtg= | |
| 6 | + | github.com/bnema/purego-xkbcommon v0.2.0/go.mod h1:GE8JGmR/rqdklz96tFaFU7M5kI7jN1ma5mh+rz+XXrg= | |
| 7 | + | github.com/bnema/wlturbo v0.6.1 h1:iprJoRs+4duIsiemPVPSmN3qdp0Nbh2iLJ5VMwcY0fY= | |
| 8 | + | github.com/bnema/wlturbo v0.6.1/go.mod h1:4i1k1wyw7FDWOkh2hg1ZwPfrPRn3+E6WrYg9Qrt74CA= | |
| 9 | 9 | github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= | |
| 10 | 10 | github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= | |
| 11 | 11 | github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= | |
| @@ -2,10 +2,10 @@ github.com/bnema/go-wayland-bindings v0.1.0 h1:mi2vNa8BB5ZCo/hq/9d6Af01yhqY6QXAZ | |||||
| 2 | github.com/bnema/go-wayland-bindings v0.1.0/go.mod h1:eWOgjp9vzZEqxm059q1G9F5NXplmv9UAmrDJiivxVjA= | 2 | github.com/bnema/go-wayland-bindings v0.1.0/go.mod h1:eWOgjp9vzZEqxm059q1G9F5NXplmv9UAmrDJiivxVjA= | ||
| 3 | github.com/bnema/purego v0.13.0-bnema.1 h1:fKRdztnvTmRqAjANMoN+utEIH73dvPqVPJh2iZCCAO8= | 3 | github.com/bnema/purego v0.13.0-bnema.1 h1:fKRdztnvTmRqAjANMoN+utEIH73dvPqVPJh2iZCCAO8= | ||
| 4 | github.com/bnema/purego v0.13.0-bnema.1/go.mod h1:xS1iX3noypxnbOUEUAqOvkfnUzgHuu19VtL4+dfUMJM= | 4 | github.com/bnema/purego v0.13.0-bnema.1/go.mod h1:xS1iX3noypxnbOUEUAqOvkfnUzgHuu19VtL4+dfUMJM= | ||
| 5 | - | github.com/bnema/purego-xkbcommon v0.1.0 h1:VHNf9shPpafKxdTERcwCNJKHhSd4IG2tjmLsDACKnuw= | 5 | + | github.com/bnema/purego-xkbcommon v0.2.0 h1:UWh5rSJIBhYImg8wZ98UzK4QNt7gvkKR6gFseO21mtg= |
| 6 | - | github.com/bnema/purego-xkbcommon v0.1.0/go.mod h1:GE8JGmR/rqdklz96tFaFU7M5kI7jN1ma5mh+rz+XXrg= | 6 | + | github.com/bnema/purego-xkbcommon v0.2.0/go.mod h1:GE8JGmR/rqdklz96tFaFU7M5kI7jN1ma5mh+rz+XXrg= |
| 7 | - | github.com/bnema/wlturbo v0.6.0 h1:sEEf22j+PIrSV9NTlognbSJ1/CUoeQj/lwpUkE6D1nY= | 7 | + | github.com/bnema/wlturbo v0.6.1 h1:iprJoRs+4duIsiemPVPSmN3qdp0Nbh2iLJ5VMwcY0fY= |
| 8 | - | github.com/bnema/wlturbo v0.6.0/go.mod h1:4i1k1wyw7FDWOkh2hg1ZwPfrPRn3+E6WrYg9Qrt74CA= | 8 | + | github.com/bnema/wlturbo v0.6.1/go.mod h1:4i1k1wyw7FDWOkh2hg1ZwPfrPRn3+E6WrYg9Qrt74CA= |
| 9 | github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= | 9 | github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= | ||
| 10 | github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= | 10 | github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= | ||
| 11 | github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= | 11 | github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= | ||
M seat_wire_test.go +6 -21
| @@ -362,27 +362,12 @@ func TestSeatRepeatThroughEpoll(t *testing.T) { | |||
| 362 | 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 | 365 | // TestAllocKey measures the steady-state key path over a real socketpair, on | |
| 379 | 366 | // the real code path (no mocks): key frames in, reader decode, queue, Dispatch | |
| 380 | 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 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). | |
| 386 | 371 | func TestAllocKey(t *testing.T) { | |
| 387 | 372 | skipUnderRace(t) | |
| 388 | 373 | c, srv, peer, s := seatSetup(t) | |
| @@ -431,11 +416,11 @@ func TestAllocKey(t *testing.T) { | |||
| 431 | 416 | } | |
| 432 | 417 | step := run(batch, 2*pairs) | |
| 433 | 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 | 420 | require.Equal(t, "a", h.lastText) | |
| 436 | 421 | ||
| 437 | 422 | // 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 | 424 | mods := func(depressed uint32) []byte { | |
| 440 | 425 | b := appendU32(appendU32(nil, 1), depressed) | |
| 441 | 426 | return frame(kb, 4, appendU32(appendU32(appendU32(b, 0), 0), 0)) | |
| @@ -449,12 +434,12 @@ func TestAllocKey(t *testing.T) { | |||
| 449 | 434 | } | |
| 450 | 435 | require.Zero(t, measure("modifiers, 100 identical masks", run(same, 100)), "identical masks cost nothing") | |
| 451 | 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 | 439 | buf := neferclient.NewSecretBuffer(4096) | |
| 455 | 440 | c.Seat().SetSecret(buf) | |
| 456 | 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 | 443 | require.Empty(t, h.lastText, "no text reaches the handler in secret mode") | |
| 459 | 444 | require.Positive(t, buf.Len()) | |
| 460 | 445 | 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, on | 365 | // 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, Dispatch | 366 | // 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 own | 369 | + | // Every path is zero-allocation: releases, text and secret presses, and |
| 383 | - | // cost, which must be zero. Presses add the purego-xkbcommon cost (see | 370 | + | // 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; a | 422 | // 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() | ||