Skip to content

perf(glyph): cache decoded glyph frames and stop ticking still tiles - #16

Merged
scttbnsn merged 1 commit into
dev/m2from
fix/dil-ui-glyph-cache
Oct 29, 2026
Merged

scttbnsn merged 1 commit into
dev/m2from
fix/dil-ui-glyph-cache

Conversation

@scttbnsn

@scttbnsn scttbnsn commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Glyph.image(frame:) read and decoded two PNGs from the bundle on every call, with no cache. It runs from the sidebar logo in body, from the menu bar animation, and from four 0.25 s TimelineViews on the Menu Bar settings page. Those tiles also kept ticking with motion off, with Reduce Motion on, or for Cat cans, which only has one awake frame.

Decoded frames are now cached per glyph and frame, so repeat calls return the same image. A new animates(motion:reduceMotion:) decides whether a tile needs the TimelineView at all, and still tiles just draw the still frame.

Measured on 1,000 calls of Glyph.bugEyes.image(frame: "on0"): about 504 ms uncached (around 0.5 ms a call) versus 0.18 ms cached.

Done when: decoded glyph frames are cached per frame and static glyphs skip TimelineView.

Verify: bash scripts/verify.sh passes. New GlyphTests check that repeat calls return the same instance, and that animates is false only where frame() is constant across elapsed times. SettingsRenderTests still pass.

Summary by CodeRabbit

  • New Features
    • Menu Bar settings previews now animate only when motion is enabled and reduced motion is off. The cat cans glyph remains still.
    • Bug eyes, can, and spiral eyes previews animate with both subtle and lively motion settings.
  • Bug Fixes
    • Repeated requests for the same glyph image and frame now reuse the loaded image.

Glyph.image(frame:) read and decoded two PNGs from the bundle on every call, including from SwiftUI body and the menu bar animation. It now caches each decoded glyph frame, which drops a call from about 0.50 ms to well under 0.001 ms (1,000 calls: 504 ms uncached, 0.18 ms cached). The Menu Bar settings tiles also render a static image instead of a 4 Hz TimelineView when motion is off, Reduce Motion is on, or the glyph has a single awake frame.
@scttbnsn

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Walkthrough

Glyph image requests now reuse successfully loaded images. Menu Bar settings previews animate only when motion is enabled, Reduce Motion is off, and the glyph is not .catCans.

Changes: Glyph preview behavior

Layer / File(s) Summary
Glyph image caching and animation policy
Sources/DilatedUI/Glyph.swift, Tests/DilatedUITests/GlyphTests.swift
Glyph.image(frame:) caches successfully loaded images by glyph and frame. Glyph.animates(motion:reduceMotion:) returns whether the glyph animates under the supplied settings. Tests check image identity across repeated requests.
Settings preview animation
Sources/DilatedUI/Settings/SettingsWindow.swift, Tests/DilatedUITests/GlyphTests.swift
Settings previews use a periodic timeline when the glyph animates under the current settings. Otherwise, they render the still frame. Tests cover animation expectations across glyphs, motion modes, and Reduce Motion settings.

Priority: Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Refactor

Merge Risk: Minimal · up to e16e1

No concrete regression is established in the changed caching or preview behavior, so the PR is mergeable with normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly summarizes the two main changes: caching decoded glyph frames and avoiding timeline updates for still glyphs.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 4 functions across 3 files.

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches: 💡 2
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@scttbnsn

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔇 Additional comments: 1
Sources/DilatedUI/Glyph.swift-30-30: 1

30-30: Minor · Functional Correctness · Quick win

⚠️ Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.

Keep caller mutations out of the cache.

If a caller changes the returned image’s size or isTemplate, later callers receive that modified image. Previously, each request returned a fresh image. Cache the decoded representations and return an independent image to each caller; update the identity test accordingly.


Review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 6af7abce-159e-4888-9d59-30f83e06202a
Commits

Reviewing files that changed from the base of the PR and between f4d58f8 and e16e14e.

Files selected for processing: 3
  • Sources/DilatedUI/Glyph.swift
  • Sources/DilatedUI/Settings/SettingsWindow.swift
  • Tests/DilatedUITests/GlyphTests.swift

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

@biggest-littlest biggest-littlest left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

@scttbnsn
scttbnsn merged commit 48a3127 into dev/m2 Oct 29, 2026
3 of 4 checks passed
@scttbnsn
scttbnsn deleted the fix/dil-ui-glyph-cache branch October 29, 2026 02:00
@scttbnsn

scttbnsn commented Nov 7, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in #110 (f2d4bf5) for the next release. Decoded glyph prototypes stay cached, while callers receive independent images and bitmap representations. The regression changes image size, template state, representation size and pixel bytes, then verifies a fresh request is unchanged. It failed before the fix and passes now. This is on dev/m2, not in the published beta.12.

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