Skip to content

perf: defer full-frame compression when a partial upload may succeed#95

Merged
g4bri3lDev merged 1 commit into
OpenDisplay:mainfrom
balloob:perf/lazy-compress-partial
Jul 5, 2026
Merged

perf: defer full-frame compression when a partial upload may succeed#95
g4bri3lDev merged 1 commit into
OpenDisplay:mainfrom
balloob:perf/lazy-compress-partial

Conversation

@balloob

@balloob balloob commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Summary

upload_image always encoded and zlib-compressed the entire frame before attempting the partial (0x76) path. When the partial upload succeeds (the common case for small changes), that full-frame compression is pure waste — 2.7 ms @800×480, 15.7 ms @1600×1200.

This PR defers full-frame compression when state is not None:

  • upload_image prepares with compress=False when a partial upload may be attempted.
  • _dispatch_upload compresses lazily on the full-upload fallback. The ZIPXL path already recompressed on window mismatch; this extends the same lazy behavior to the non-ZIPXL branch.

Correctness

  • state is None (plain full upload): unchanged — prepare_image still compresses eagerly, and _dispatch_upload's new elif compressed_data is None branch is never taken.
  • state is not None, partial succeeds: full-frame compression skipped entirely (the win).
  • state is not None, fallback to full: _dispatch_upload compresses with the same window bits prepare_image would have used (ZIPXL=9 / DEFAULT=15), so the bytes on the wire are identical to before — just computed later.

Test plan

  • uv run pytest -q → 439 passed
  • ruff check, ruff format, mypy clean

🤖 Generated with Claude Code

upload_image always encoded and zlib-compressed the whole frame before
attempting the partial (0x76) path. When the partial upload succeeds, that
compression (2.7ms @800x480, 15.7ms @1600x1200) is pure waste. Skip it when
state is not None by preparing with compress=False, and compress lazily in
_dispatch_upload on the full-upload fallback. The zipxl path already
recompressed on window mismatch; extend the same lazy behavior to the
non-zipxl branch so the fallback produces byte-identical output to before.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JRrm95f1qNZzDM9r2SB6KW
@balloob balloob requested a review from g4bri3lDev as a code owner July 4, 2026 06:36
@codecov

codecov Bot commented Jul 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.71429% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/opendisplay/device.py 85.71% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@g4bri3lDev g4bri3lDev merged commit c8b398a into OpenDisplay:main Jul 5, 2026
6 checks passed
g4bri3lDev added a commit to balloob/py-opendisplay that referenced this pull request Jul 5, 2026
Semantic conflict between OpenDisplay#95 and OpenDisplay#96: the lazy compression branch for
non-ZIPXL devices referenced DEFAULT_ZLIB_WINDOW_BITS, which device.py
never imported (NameError at runtime), and even spelled correctly a
15-bit window is rejected by current firmware — prepare_image has
compressed everything at 9 bits since OpenDisplay#96. The deferred path now uses
the same 9-bit window. ZIPXL window repair and the non-ZIPXL 50KB size
gate keep their existing behavior.
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.

2 participants