Skip to content

Performance: start times only for rows in view, cheaper library search - #22

Merged
epell-development merged 3 commits into
mainfrom
claude/project-thread-avobqn
Oct 26, 2026
Merged

epell-development merged 3 commits into
mainfrom
claude/project-thread-avobqn

Conversation

@epell-development

Copy link
Copy Markdown
Owner

Requested by epell · project thread

Next round of performance work for 0.2.9 ("Continue with performance upgrades").

How it was measured

I ran a release build under a virtual display with 3 playlists (6,500 rows), a 20,000-track library and playback running, then timed each part of the frame and took CPU profiles. While playing, the UI work per frame dropped from about 2.1 ms to 0.8 ms. The two biggest costs were the playlist view (0.9 ms) and the player bar (0.67 ms). Both were adding up start times for the whole on-air list, every frame.

Changes

  • Start times are worked out lazily (Playout::starts → Starts::get). Only the rows being drawn are calculated, plus rows up to the next hour marker, because that marker can still mark them as skipped. projected_starts is now built on the same code. The playlist view, the player's hour-marker countdown, the Clock tab and Additional playlist views all use the lazy version.
  • Library search lower-cases each track once per library version instead of three to four times on every keystroke. Typing more letters only filters the tracks already shown. The cache is reset when switching between local and server sessions, because their version numbers can collide.
  • Waveform analysis (smart fading) reads files at their own sample rate instead of resampling them to 22.05 kHz first. A 200 s MP3 now takes about 15% less time.
  • Playlist tab strip: only the hovered tab's total length is added up, for its tooltip.
  • Hour lines: hours are compared as (date, hour) instead of formatting a string per row every 2 s.

Tests

  • New: start_times_worked_out_on_demand_match_the_whole_list checks that lazy start times match the full calculation for every row. The list has soft, hard and waiting markers, both late and early, and the rows are asked for out of order.
  • New: any_channel_count_becomes_left_right_pairs covers the analysis input with mono, stereo and 5.1.
  • cargo fmt, cargo build (no warnings) and cargo test all pass. This PR adds no new clippy warnings.

Generated by Claude Code

…earch

Profiled with 3 playlists (6,500 rows) and a 20,000-track library: the UI
work per frame while playing went from about 2.1 ms to 0.8 ms.

- Start times are worked out only as far as they are needed (the rows on
  screen, up to the next hour marker that may skip them) instead of for the
  whole list, twice per frame. The player's hour-marker countdown, the
  Clock tab and Additional playlist views use the same lazy calculation.
- Library search lower-cases each track once per library change, not on
  every keystroke, and typing more letters only narrows the tracks already
  shown.
- Waveform analysis for smart fading reads files at their own sample rate
  instead of resampling them first.
- Playlist tabs only add up a tab's length when its tooltip is wanted, and
  hour lines compare hours without building a string per row.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AqiVGDcxKHnYv84gryaby
@epell-development epell-development self-assigned this Oct 25, 2026

@mergeguards mergeguards 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.

MergeGuard review
Risk: 🟠 35/100 — moderate
Findings: 🟠 1 medium
Open Files changed for 1 inline review thread on the diff.

💡 Use the Fix All MergeGuard Findings checkbox comment on this PR to apply auto-fixes in batch, or reply @mergeguards fix on any inline finding.


Reviewed by MergeGuard AI

Comment thread src/playout.rs
@mergeguards

mergeguards Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

MergeGuard agent actions

Fix all findings

All issues (1)
  • medium · src/app.rs:2166 — Library search optimization uses index-based filtering on lib_lower without bounds checking. The closure hit accesses text[i] and text[i].1 but if shown contains stale indices after libra…

Apply auto-fixes for the findings above on this branch:

  • Fix All MergeGuard Findings

Or reply with @mergeguards fix-all on this pull request.

Conflicts: start times now use the station clock (`Playout::now`), and the
Additional playlist view passes `row_missing` to `row_text_color`.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AqiVGDcxKHnYv84gryaby

@mergeguards mergeguards 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.

✅ MergeGuard — new commits are on this pull request.

Re-scan the latest diff: paste this line by itself (copy/paste is fine) — either on the Conversation tab (Add a comment) or on Files changed as a comment on the diff:

@mergeguard-followup

@mergeguards mergeguards 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.

MergeGuard review
Risk: 🟠 35/100 — moderate
Findings: 🟠 1 medium
Open Files changed for 1 inline review thread on the diff.

💡 Use the Fix All MergeGuard Findings checkbox comment on this PR to apply auto-fixes in batch, or reply @mergeguards fix on any inline finding.


Reviewed by MergeGuard AI

Comment thread src/playout.rs
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AqiVGDcxKHnYv84gryaby

@mergeguards mergeguards 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.

✅ MergeGuard — new commits are on this pull request.

Re-scan the latest diff: paste this line by itself (copy/paste is fine) — either on the Conversation tab (Add a comment) or on Files changed as a comment on the diff:

@mergeguard-followup

@mergeguards mergeguards 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.

MergeGuard review
Risk: 🟠 35/100 — moderate
Findings: 🟠 1 medium
Open Files changed for 1 inline review thread on the diff.

💡 Use the Fix All MergeGuard Findings checkbox comment on this PR to apply auto-fixes in batch, or reply @mergeguards fix on any inline finding.


Reviewed by MergeGuard AI

Comment thread src/app.rs
@epell-development
epell-development merged commit 0b7ac66 into main Oct 26, 2026
6 checks passed
epell-development pushed a commit that referenced this pull request Oct 26, 2026
Keeps this branch's server update check (selfupdate, ServerCfg.check_updates)
as the one source of ServerInfo.latest and drops #19's second update thread;
the release page now comes from the same release. AzuraCast calls from the
portal need the AzuraCast permission. Playlist Insert/RemoveRows commands need
edit_playlists. The generator's category folder picker (moved to genui.rs)
goes through App::pick.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V5uW8ddhUDidYMFx9SLghq
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