Skip to content

perf(present): zero-dispatch RGBA pack + zero-alloc fallback (measured 4-4.6x) - #6

Merged
tannevaled merged 1 commit into
mainfrom
perf/present-pack-zero-dispatch
Aug 9, 2026
Merged

perf(present): zero-dispatch RGBA pack + zero-alloc fallback (measured 4-4.6x)#6
tannevaled merged 1 commit into
mainfrom
perf/present-pack-zero-dispatch

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

Performance audit of the per-frame present/pack path

Audit horodate: 2026-08-09 12:25 CEST. Measure-first: benchmarked before changing anything, fixed only proven costs, behaviour byte-identical.

Findings

Both live present paths were already zero-alloc per frame — X11 MIT-SHM packs directly into the mmap'd shared segment, Wayland directly into the wl_shm pool. The double-buffer swap allocates nothing. So the only remaining cost was CPU in the RGBA->wire conversion:

  1. Wayland PackARGB8888 wrote each pixel through the binary.ByteOrder interface (NativeOrder.PutUint32) — ~2M indirect calls/frame at 1080p. Now uses the concrete binary.NativeEndian (inlines to a word store) + per-row reslicing for BCE.
  2. X11 EncodeRectInto/encodeRegion packed per pixel via pixel()+putValue() method calls with per-byte inner loops. New shared packRect picks one of three byte-identical strategies once at NewPresenter time: zero-arithmetic fast path for the ubiquitous 32-bpp 8:8:8 TrueColor visual, word-wise generic-shift path for other 32-bpp visuals, per-channel path for non-32-bpp depths. Writes keyed by server image byte order (host-independent; s390x-safe).
  3. Non-SHM PutImage fallback allocated ~8.3 MB/frame; now reuses a persistent per-Presenter scratch -> 0 allocs/present.

Measured (Apple M4 Max, 1920x1080, -benchmem), before -> after

bench before after gain allocs
x11 EncodeRectInto full 7.50 ms 1.64 ms 4.6x 0
x11 EncodeRectInto 64x64 14.9 us 3.43 us 4.3x 0
x11 encodeRegion full (fallback) 7.96 ms + 8.3 MB 1.66 ms 4.8x 8.3 MB/present -> 0
wl PackARGB8888 full 4.35 ms 1.09 ms 4.0x 0
wl PackARGB8888 64x64 8.43 us 2.22 us 3.8x 0

Committed Benchmark* (full-frame + damage-rect) added for both backends.

Conformance

  • internal/x11 + internal/wayland stay at 100% statement coverage.
  • -race (CGO=1) clean; whole module tests pass.
  • CGO=0 cross-build clean on all six supported arches (amd64/arm64/riscv64/loong64/ppc64le/s390x) + darwin stub.
  • No syscall usage touched — stays behind existing linux gating; the v0.3.1 syscall-leak fix is untouched.

🤖 Generated with Claude Code

… alloc (measured 4-4.6x)

Audit of the per-frame present/pack path (2026-08-09 12:25 CEST). Both live
paths were already zero-alloc — X11 MIT-SHM packs straight into the mmap'd
segment, Wayland into the wl_shm pool — so the remaining cost was pure CPU in
the RGBA->wire conversion. Measured before optimizing.

Real hotspots found + fixed:

- Wayland PackARGB8888 called NativeOrder.PutUint32 through the
  binary.ByteOrder INTERFACE once per pixel (~2M indirect calls/frame at
  1080p). Switched to the concrete binary.NativeEndian (inlines to a word
  store) + per-row reslicing for bounds-check elimination. Endianness
  behaviour is identical (native ARGB for a same-machine compositor).

- X11 EncodeRectInto/encodeRegion packed per pixel via pixel()+putValue()
  method calls with per-byte inner loops. Added a shared packRect with three
  byte-identical strategies chosen once at NewPresenter time: a
  zero-arithmetic fast path for the ubiquitous 32-bpp 8:8:8 TrueColor visual,
  a word-wise generic-shift path for other 32-bpp visuals, and the original
  per-channel path for non-32-bpp depths. Writes go through binary.Big/Little
  Endian keyed by the server image byte order (host-independent, s390x-safe).

- Non-SHM PutImage fallback allocated an 8.3 MB wire buffer per frame; now
  reuses a persistent per-Presenter scratch (grows only when the frame grows)
  -> 0 allocs/present.

Measured (Apple M4 Max, 1920x1080, -benchmem), before -> after:
  x11 EncodeRectInto full      7.50 ms ->  1.64 ms   (4.6x), 0 allocs
  x11 EncodeRectInto 64x64     14.9 us ->  3.43 us   (4.3x), 0 allocs
  x11 encodeRegion full (fb)   7.96 ms ->  1.66 ms   + 8.3 MB/present -> 0
  wl  PackARGB8888 full        4.35 ms ->  1.09 ms   (4.0x), 0 allocs
  wl  PackARGB8888 64x64       8.43 us ->  2.22 us   (3.8x), 0 allocs

Committed Benchmark* (full-frame + damage-rect) added for both backends.
internal/x11 + internal/wayland stay at 100% statement coverage; -race clean;
CGO=0 cross-build clean on all six supported arches + darwin stub. No syscall
usage touched (stays behind the existing linux gating).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit 4424c52 into main Aug 9, 2026
19 checks passed
@tannevaled
tannevaled deleted the perf/present-pack-zero-dispatch branch August 9, 2026 13:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant